3

の最初の目標は、エディット コントロール内に X ボタンを配置することでした (後で、このエディット コントロール自体がコンボ ボックスの一部であることが判明しました)。この記事をガイダンスとして使用することをお勧めします。

少し「きれい」に見せるために、代わりにその X ボタンにツールバーを使用することにしました。そこで、次のコードを思いつきました。ComboBox 内でコントロールを初期化する方法は次のとおりです。

//Initialization
#define EDIT_X_TOOLBAR_BTN_W 10
#define EDIT_X_TOOLBAR_BTN_H 11

//Find edit control handle using GetComboBoxInfo() API
COMBOBOXINFO cbi2 = {0};
cbi2.cbSize = sizeof(cbi2);
GetComboBoxInfo(hComboWnd, &cbi2);
HWND hEditCtrl = cbi2.hwndItem;

HINSTANCE hInst = ::GetModuleHandle(NULL);

//Create toolbar as a child of the edit control
hWndToolbar = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 
    WS_CHILD | WS_VISIBLE | 
    CCS_NODIVIDER | CCS_NOPARENTALIGN | 
    CCS_NORESIZE | CCS_NOMOVEY | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT,
    0, 0, 0, 0, 
    hEditCtrl,
    (HMENU)ID_CMD_EDIT_X_TOOLBAR, hInst, 0);

::SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
::SendMessage(hWndToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(EDIT_X_TOOLBAR_BTN_W, EDIT_X_TOOLBAR_BTN_H));
::SendMessage(hWndToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(EDIT_X_TOOLBAR_BTN_W, EDIT_X_TOOLBAR_BTN_H));

//Load bitmap
TBADDBITMAP tbab = {0};
tbab.hInst = hInst;
tbab.nID = IDB_BITMAP_TOOLBAR_X;
VERIFY(::SendMessage(hWndToolbar, TB_ADDBITMAP, 1, (LPARAM)&tbab) != -1);

TBBUTTON tbbs[1] = {0};
tbbs[0].iBitmap = 0;
tbbs[0].idCommand = CMD_EDIT_X_TOOLBAR_CLOSE;
tbbs[0].fsState = TBSTATE_ENABLED;
tbbs[0].fsStyle = TBSTYLE_BUTTON;
tbbs[0].iString = -1;

VERIFY(::SendMessage(hWndToolbar, TB_ADDBUTTONS, SIZEOF(tbbs), (LPARAM)tbbs));

//Subclass edit control
oldProc = (WNDPROC)::SetWindowLong(hEditCtrl, GWL_WNDPROC, (LONG)wndProcEditCtrl);

//And redraw the edit control
::SetWindowPos(hEditCtrl, NULL, 0, 0, 0, 0, 
    SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);

これは、エディット コントロールのサブクラス化されたウィンドウ プロシージャです。

CRect rcToolbar;

LRESULT CALLBACK wndProcEditCtrl(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_NCCALCSIZE:
        {
            if(wParam)
            {
                //First let edit box process it
                ::CallWindowProc(oldProc, hWnd, msg, wParam, lParam);

                RECT* pRc = (RECT*)lParam;

                //Define toolbar size & move it
                int nTB_w = pRc->bottom - pRc->top;
                int nTB_h = nTB_w;

                //Adjust the edit's client area
                pRc->right -= nTB_w;

                //Set toolbar rect
                rcToolbar.SetRect(pRc->right, pRc->top, pRc->right + nTB_w, pRc->top + nTB_h);

                //And move the toolbar
                ::MoveWindow(hWndToolbar, pRc->right, pRc->top, nTB_w, nTB_h, TRUE);

                return 0;
            }
        }
        break;

    case WM_NCHITTEST:
        {
            POINT pnt;
            pnt.x = GET_X_LPARAM(lParam);
            pnt.y = GET_Y_LPARAM(lParam);

            if(::ScreenToClient(hWnd, &pnt))
            {
                if(rcToolbar.PtInRect(pnt))
                {
                    return HTBORDER;
                }
            }
        }
        break;
    }

    return ::CallWindowProc(oldProc, hWnd, msg, wParam, lParam);
}

問題は、ツールバーが (Spy++ 経由で) 作成されていることを確認できますが、非アクティブなままで、ボタンが表示されないことです (右側の灰色の四角形だけが表示されます)。

ここに画像の説明を入力

ツールバー自体を確実に作成できるようにするために、その親ウィンドウをエディット コントロール (つまりhEditCtrl) からメイン ダイアログ ウィンドウに変更すると、(間違った場所に) 表示され、クリックに問題なく応答します。したがって、私の結論は、サブクラスでいくつかのメッセージをブロックする必要があるということです。問題はどれですか?

ここで何が欠けているのですか?

4

0 に答える 0