2017-03-04 3 views
0

Ich habe Button-Steuerelemente in einem Dialogfeld mit WinAPI erstellt und ich handle WM_NOTIFY -> NM_CUSTOMDRAW. Der Dialog wird durch einen Menübefehl erstellt. Das seltsame Verhalten ist folgendes: Wenn ich den Menübefehl über die Tastatur auslocke (Drücken der Enter-Taste auf dem Menüpunkt), ist alles in Ordnung. Wenn ich mit der Maus auf den Menüeintrag klicke, um das Dialogfeld zu öffnen, wird durch Drücken der Alt-Taste der Text auf der Schaltfläche entfernt, bis ich auf eine Schaltfläche klicke oder die Maus bewege. Dies geschieht einmal im Leben jedes Dialogs. Wie kann ich dieses Verhalten verhindern? Ich zeichne den Hintergrund von Tasten und lasse Fenster Text und Bitmap darauf zeichnen. Was ist das Problem mit meinem Code? Hier ist ein Teil meines Code:Seltsames Verhalten beim benutzerdefinierten Zeichnen einer Schaltfläche

/*---------------------------------------------------------*/ 
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; 
} 

Vielen Dank im Voraus mr.abzadeh EDIT1: Frage neu geschrieben, um besser das Problem zu beschreiben und von anderen nutzbar zu machen. EDIT2: Ich habe festgestellt, dass dieses Verhalten vollständig mit Tastatur Zugriff in Fenstern implementiert ist. Ich habe das Control Panel/Access Center geöffnet/Die Tastatur einfacher zu benutzen -> markiert Kontrollkästchen "Tastaturkürzel und Zugriffstasten unterstreichen" und das Problem ist gelöst. Aber ich möchte das Problem lösen, ohne die Bedienfeldeinstellungen zu ändern. EDIT3: Auf andere Weise habe ich WM_KEYDOWN -Ereignis von Steuerelementen erfasst und eine benutzerdefinierte Nachricht an Dialog, die alle Schaltflächen im Dialogfeld neu streichen müssen, wenn die ALT-Taste zum ersten Mal gedrückt wird, und dies löst mein Problem behoben. Aber ich lasse die Frage offen, ob es einen besseren Weg gibt.

+0

Sie sollten den ursprünglichen Pinsel und Stift nach dem Ändern wiederherstellen. Könnte verwandt sein. –

+0

Speichern und Wiederherstellen von GDI-Objekten macht keinen Unterschied, wie ich erwartet hatte. –

+0

Wiederherstellen der DC wird nicht Ihr spezifisches Problem beheben, aber Sie sollten es immer noch tun. – Anders

Antwort

0

Das Malen als Antwort auf CDDS_PREPAINT ist wahrscheinlich problematisch, weil Sie Windows bitten, den Hintergrund in bestimmten Szenarien mit CDRF_DOERASE zu zeichnen.

Versuchen Sie einfach CDRF_DOERASE in CDDS_PREPAINT zurückgeben und die tatsächliche Zeichnung in einem späteren Stadium, vielleicht in CDDS_POSTERASE.

+0

Zeichnungshintergrund in CDDS_POSTPAINT ist schlechter, weil mein Code Text und Bitmap löscht; Ich habe CDRF_DOERASE in CDRF_NEWFONT geändert –

+0

Ich dachte, dass Sie diese selbst zeichnen wollten, wenn nicht, dann verzögern Sie, um nachzumalen. Beachten Sie, dass RoundRect das Rechteck füllt, es sei denn, der Pinsel ist hohl! Wenn Sie den Hintergrund und Windows zeichnen möchten, um den Text und das Symbol zu zeichnen, bin ich mir nicht sicher, ob das möglich ist (versuchen Sie vielleicht skipdefault in der Phase vor dem Löschen), aber Sie können diese selbst zeichnen. – Anders

+0

Mir ist aufgefallen, dass dieses Problem vollständig mit dem Zugriff auf die Tastatur verbunden ist. Ich habe das Control Panel/Access Center geöffnet/Die Tastatur einfacher zu bedienen -> aktiviert "Unterstreichen Tastaturkürzel und Zugriffstasten" und das Problem ist vollständig gelöst. Jetzt zeichnet der obige Code Hintergrund und Windows zeichnet Text und Bitmap. –

Verwandte Themen