2017-03-04 9 views
0

私はwinapiを使ってダイアログにボタンコントロールを作成しましたが、WM_NOTIFY - > NM_CUSTOMDRAWを処理します。 ダイアログはメニューコマンドで作成されます。私がキーボードでメニューコマンドを起動すると(メニュー項目のEnterキーを押す)、すべてのことがOKです。メニュー項目をクリックしてダイアログボックスを開くと、Altキーを押すとボタン上のテキストが削除され、ボタンをクリックするかマウスを移動します。 Tisは、すべてのダイアログの生存期間中に一度発生します。どのように私はこの動作を防ぐことができますか?私はボタンの背景を描画し、ウィンドウにテキストとビットマップを描画させます。私のコードの問題は何ですか?ここに私のコードの一部です:事前にボタンをカスタムドローするときの異常な動作

/*---------------------------------------------------------*/ 
static int uOnPrePaint(HWND hDlg, LPARAM lParam) 
{ 
    LPNMCUSTOMDRAW lpnmCD = (LPNMCUSTOMDRAW)lParam; 
    COLORREF crPen = GetDCPenColor(lpnmCD->hdc); 
    bool bHot = (lpnmCD->uItemState & CDIS_HOT) != 0; 
    COLORREF crBack = RGB(200, 200, 200); 
    COLORREF crHot = RGB(200, 200, 0); 
    SetDCBrushColor(lpnmCD->hdc, bHot ? crHot : crBack); 
    SetDCPenColor(lpnmCD->hdc, bHot ? crHot : crBack); 
    SelectObject(lpnmCD->hdc, GetStockObject(DC_BRUSH)); 
    SelectObject(lpnmCD->hdc, GetStockObject(DC_PEN)); 
    int iThickness = 3; 
    RoundRect(lpnmCD->hdc, 
     lpnmCD->rc.left + iThickness, 
     lpnmCD->rc.top + iThickness, 
     lpnmCD->rc.right - iThickness, 
     lpnmCD->rc.bottom - iThickness, 
     5, 
     5 
    ); 
    SetDCPenColor(lpnmCD->hdc, crPen); 
    SetWindowLongPtrW(hDlg, DWL_MSGRESULT, CDRF_DOERASE); 
    return TRUE; 
} 

/*---------------------------------------------------------*/ 
static int uCustomDraw(HWND hwndDlg, LPARAM lParam) 
{ 
    LPNMCUSTOMDRAW lpnmCD = (LPNMCUSTOMDRAW)lParam; 
    switch (lpnmCD->dwDrawStage) 
    { 
    case CDDS_PREPAINT: return uOnPrePaint(hwndDlg, lParam); 
    default: return (INT_PTR)0; 
    } 
} 

/*---------------------------------------------------------*/ 
static int uOnNotify(HWND hwndDlg, WPARAM wParam, LPARAM lParam) 
{ 
    LPNMHDR lpnmHeader = (LPNMHDR)lParam; 
    switch (lpnmHeader->code) 
    { 
    case NM_CUSTOMDRAW: return uCustomDraw(hwndDlg, lParam); 
    default: return (INT_PTR)0; 
    } 
} 

/*---------------------------------------------------------*/ 
static HWND uCreateButton(HWND hWnd, int cpx, int cpy, int cpWidth, int cpHeight, const wchar_t * wszText, int iIdControl) 
{ 
    int style = BS_TEXT | BS_NOTIFY | BS_VCENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_GROUP; 
    int styleEx = WS_EX_RTLREADING | WS_EX_RIGHT; 
    HWND hwndControl = CreateWindowExW(
     styleEx, L"BUTTON", wszText, style, 
     cpx, cpy, cpWidth, cpHeight, 
     hWnd, nullptr, g_hInstance, nullptr 
    ); 
    //ShowWindow(hwndControl, SW_SHOW); 
    SetWindowLongPtrW(hwndControl, GWLP_ID, iIdControl); 
    unsigned cpImageWidth = 16; 
    HICON hIcon1 = (HICON)LoadImageW(g_hInstance, 
     MAKEINTRESOURCEW(IDI_SMALL), IMAGE_ICON, cpImageWidth, cpImageWidth, LR_SHARED); 
    if (hIcon1) 
    SendMessageW(hwndControl, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hIcon1); 
    return hwndControl; 
} 

おかげで mr.abzadeh EDIT1:より良い問題を説明し、他の人によってそれが使用できるように書き換え質問。 EDIT2:この動作は、Windowsで実装されたキーボードのアクセスの容易さに完全に関連していることに気付きました。コントロールパネルを開く/アクセスセンターを簡単にする/キーボードを使いやすくする - > [キーボードショートカットとアクセスキーに下線を付ける]チェックボックスをオンにして問題を解決しました。しかし、私はコントロールパネルの設定を変更せずに問題を解決したい。 EDIT3:別の方法で、コントロールのWM_KEYDOWNイベントをキャプチャし、ダイアログボックスにカスタムメッセージを投稿しました。ダイアログボックスのすべてのボタンを再ペイントする必要がありました。 ALTキーが初めて押されたときに問題が解決されました。しかし、より良い方法があるかどうかを知るために質問を開いたままにします。

+0

元のブラシとペンを交換した後に復元する必要があります。関連するかもしれない。 –

+0

gdiオブジェクトの保存と復元は、私が期待したように違いはありません。 –

+0

DCの復元は、あなたの特定の問題を修正するつもりはありませんが、それでもやるべきです。 – Anders

答えて

0

CDDS_PREPAINTに対するペイントは、ウィンドウにCDRF_DOERASEという特定のシナリオで背景を描画するよう求めているため、おそらく問題があります。

CDRF_DOERASECDDS_PREPAINTに戻し、後で実際の図面をCDDS_POSTERASEにしてください。

+0

私のコードはテキストとビットマップをクリアするので、CDDS_POSTPAINTの背景を描画するのは悪いです。私はCDRF_DOERASEをCDRF_NEWFONTに変更しました –

+0

あなたがそれらを描くと思っていました。ブラシが中空でない限り、RoundRectは四角形を塗りつぶします。背景とWindowsを描画してテキストとアイコンを描きたい場合は、可能であれば(おそらくpreeraseステージでskipdefaultを試してみてください)、自分で描くことができます。 – Anders

+0

私はこの問題がキーボードのアクセスの容易さに完全に関係していることに気付きました。私はコントロールパネルを開きました/アクセスセンターのしやすさ/キーボードを使いやすくする - >「キーボードショートカットとアクセスキーに下線を付ける」をチェックして問題を完全に解決しました。上記のコードは背景を描画し、ウィンドウはテキストとビットマップを描画します。 –

関連する問題