第347章で作った透明ウィンドウを、既存(人様)のウィンドウにも適用できないでしょうか。
実はできます。
たとえば、メモ帳を半透明にできると、その下にあるウィンドウなどを確認できて便利かもしれません。また、タスクバーを半透明にしておくと、それなりに便利かもしれません。
プログラムを実行すると左の図のようなダイアログボックスが出現します。
照準のようなものをドラッグすると、アイコンがこの図形になります。そして、目的のウィンドウのところまでドラッグしてボタンを放します。
そうすると、そのWindowのアルファが指定数値のものになります。(100が完全不透明、0が完全透明)。この数値を変更するには、スライダーを動かすか、エディットコントロールに直接数値を書き込みます。
左の図は、このツールを使ってタスクバーを半透明にしたものです。タスクバーの下にある壁紙やウィンドウが透けて見えています。
では、どのように作ればよいのでしょうか。
SetLayeredWindowAttributes関数を使うには、そのウィンドウの拡張スタイルにWS_EX_LAYEREDを持っていなくてはいけません。(普通はこんなスタイルは持っていない)
そこで、GetWindowLong関数で、そのウィンドウの拡張スタイルを調べます。それに、WS_EX_LAYEREDを付け加えれば良いですね。
人様のWindowのハンドルを調べる手法は第102章のものをそのまま流用しています。
では、プログラムを見てみましょう。
// transwin01.rcの一部
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
MYDLG DIALOGEX 0, 0, 158, 126
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION
CAPTION "猫でもわかる透明化"
FONT 9, "MS ゴシック", 400, 0, 0x80
BEGIN
    DEFPUSHBUTTON   "終了(&X)",IDOK,7,105,140,14
    CONTROL         "MYBMP",IDC_MYSTATIC,"Static",SS_BITMAP | 
                    SS_REALSIZEIMAGE,7,7,17,17,WS_EX_CLIENTEDGE
    CONTROL         "",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH | 
                    TBS_NOTICKS | WS_TABSTOP,7,56,140,15
    LTEXT           "Alpha",IDC_STATIC,38,84,21,8
    EDITTEXT        IDC_EDIT1,69,81,49,14,ES_AUTOHSCROLL | ES_NUMBER
END
/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//
MYBMP                   BITMAP                  "bitmap1.bmp"
DUMMY                   BITMAP                  "bitmap2.bmp"
/////////////////////////////////////////////////////////////////////////////
//
// Cursor
//
MYCURSOR                CURSOR                  "cursor1.cur"
ビットマップは48*48のものを使いました。カーソルもその大きさのものです。MYBMPは二重丸にバツ印のものです。DUMMY何も描かれていないビットマップです。カーソルはMYBMPと同じ図形です。
// transwin01.cpp
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
BOOL CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL bCap;
HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
                   LPSTR lpsCmdLine, int nCmdShow)
{
    hInst = hCurInst;
    DialogBox(hCurInst, "MYDLG", NULL, (DLGPROC)MyDlgProc);
    return 0;
}
_WIN32_WINNTを0x0500以上に設定しておかないと、SetLayeredWindowAttributes関数が使えないので注意してください。
BOOL CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
    static HWND hStatic, hTarget, hSlider, hEdit;
    static HBITMAP hBmp, hBmpDummy;
    static HCURSOR hCursor, hArrow;
    POINT pt;
    POINTS pts;
    LONG lStyle;
    int nPos = 100;
    char szBuf[16];
    static BYTE bAlpha;
    switch (msg) {
        case WM_INITDIALOG:
            hStatic = GetDlgItem(hDlg, IDC_MYSTATIC);
            hSlider = GetDlgItem(hDlg, IDC_SLIDER1);
            SendMessage(hSlider, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 100));
            SendMessage(hSlider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)100);
            hEdit = GetDlgItem(hDlg, IDC_EDIT1);
            SetWindowText(hEdit, "100");
            hBmp = (HBITMAP)LoadImage(hInst,
                "MYBMP",
                IMAGE_BITMAP,
                0, 0,
                LR_DEFAULTCOLOR);
            hBmpDummy = (HBITMAP)LoadImage(hInst,
                "DUMMY",
                IMAGE_BITMAP,
                0, 0,
                LR_DEFAULTCOLOR);
            hCursor = (HCURSOR)LoadImage(hInst,
                "MYCURSOR",
                IMAGE_CURSOR,
                48, 48,
                LR_DEFAULTCOLOR | LR_SHARED);
            hArrow = (HCURSOR)LoadImage(NULL,
                MAKEINTRESOURCE(IDC_ARROW),
                IMAGE_CURSOR,
                0, 0,
                LR_DEFAULTCOLOR | LR_SHARED);
            return TRUE;
        case WM_LBUTTONDOWN:
            SendMessage(hStatic, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmpDummy);
            
            SetCursor(hCursor);
            SetCapture(hDlg);
            bCap = TRUE;
            return TRUE;
        case WM_LBUTTONUP:
            ReleaseCapture();
            bCap = FALSE;
            SetCursor(hArrow);
            SendMessage(hStatic, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBmp);
            pts = MAKEPOINTS(lp);
            pt.x = pts.x;
            pt.y = pts.y;
            ClientToScreen(hDlg, &pt);
            hTarget = WindowFromPoint(pt);
            if (hTarget == NULL) {
                MessageBox(hDlg, "Error", "Error", MB_OK);
                return FALSE;
            }
            lStyle = GetWindowLong(hTarget, GWL_EXSTYLE);
            lStyle |= WS_EX_LAYERED;
            SetWindowLong(hTarget, GWL_EXSTYLE, WS_EX_LAYERED);
            bAlpha = 255 * nPos / 100;
            SetLayeredWindowAttributes(hTarget, 0, bAlpha, LWA_ALPHA);
            return TRUE;
        case WM_HSCROLL:
            nPos = (int)SendMessage(hSlider, TBM_GETPOS, 0, 0);
            wsprintf(szBuf, "%d", nPos);
            SetWindowText(hEdit, szBuf);
            
            if (hTarget) {
                bAlpha = 255 * nPos / 100;
                SetLayeredWindowAttributes(hTarget, 0, bAlpha, LWA_ALPHA);
            }
            return TRUE;
        case WM_COMMAND:
            switch (LOWORD(wp)) {
                case IDOK:
                    DeleteObject(hBmp);
                    DeleteObject(hBmpDummy);
                    EndDialog(hDlg, IDOK);
                    return TRUE;
                
                case IDC_EDIT1:
                    if (HIWORD(wp) != EN_CHANGE)
                        return FALSE;
                    GetWindowText(hEdit, szBuf, sizeof(szBuf) - 1);
                    nPos = atoi(szBuf);
                    if (nPos > 100)
                        nPos = 100;
                    if (nPos < 0)
                        nPos = 0;
                    SendMessage(hSlider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)nPos);
                    if (hTarget) {
                        bAlpha = 255 * nPos / 100;
                        SetLayeredWindowAttributes(hTarget, 0, bAlpha, LWA_ALPHA);
                    }
                    return TRUE;
            }
            return FALSE;
    }
    return FALSE;
}
WM_INITDIALOGメッセージが来たら、ハンドル類を取得してstaticな変数に格納しておきます。WM_LBUTTONDOWNメッセージが来たら、マウスキャプチャー開始です。マウスキャプチャーについては第101章を参照してみてください。
ピクチャーコントロールのビットマップを変更するにはSTM_SETIMAGEメッセージを使います。
SendMessage( (HWND) hWnd, STM_SETIMAGE, (WPARAM) wParam, (LPARAM) lParam );hWndには、ウィンドウハンドルを指定します。
wParamには、イメージの種類を指定します。
IMAGE_BITMAP、IMAGE_CURSOR、IMAGE_ENHMETAFILE、IMAGE_ICONの中から指定します。
lParamには、イメージのハンドルを指定します。
WM_LBUTTONUPメッセージが来たら、キャプチャー終了です。その位置の座標を取得してWindowFromPoint関数で、ウィンドウハンドルを取得します。 そして、そのウィンドウのアルファをbAlphaに設定します。
WM_HSCROLLメッセージが来たら、スライダーコントロールの位置を取得します。 スライダーコントロールの通知メッセージは忘れやすいので注意してください。 そして、スライダーコントロールのつまみの位置をエディットコントロールに表示します。 その後、SetLayeredWindowAttributes関数を使って、ウィンドウのアルファを変更します。
「終了」ボタン(IDOK)が押されたら、ハンドル類の後始末をします。カーソルハンドルはLR_SHAREDなので、システムが処理してくれます。
エディットコントロールが変更されたら、その数値を読み取り、スライダーコントロールのつまみ位置を、それに移動します。そして、アルファを変更します。
Update 25/Mar/2004 By Y.Kumei