2017-03-04 3 views
0

winapi를 사용하여 대화 상자에서 단추 컨트롤을 만들고 WM_NOTIFY -> NM_CUSTOMDRAW를 처리했습니다. 대화 상자는 메뉴 명령에 의해 생성됩니다. 이상한 동작은 다음과 같습니다. 키보드로 메뉴 명령을 실행하면 (메뉴 항목에서 Enter 키를 누르면) 모든 것이 정상입니다. 마우스로 메뉴 항목을 클릭하여 대화 상자를 열면 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

나는 그 자신을 그리기 원한다고 생각했는데 그렇지 않다면 지연하여 그림 그리기를 연기했습니다. 브러시가 비어 있지 않으면 RectRect가 사각형을 채 웁니다. 배경 및 Windows 그리기 텍스트 및 아이콘을 그리려면 가능한 경우 (어쩌면 preerase 단계에서 skipdefault 시도하십시오)하지만 난 그냥 자신을 그릴 수 있는지 모르겠습니다. – Anders

+0

이 문제는 키보드의 액세스 용이성과 관련이 있습니다. 나는 제어판을 열었습니다/액세스 센터의 용이성/키보드를 사용하기 쉽게 만들기 -> "키보드 단축키 및 액세스 키에 밑줄 긋기"를 선택하면 문제가 완전히 해결되었습니다. 이제 위의 코드는 배경을 그리고 윈도우는 텍스트와 비트 맵을 그립니다. –

관련 문제