2014-11-07 9 views
5

Tworzę okno dialogowe za pomocą CreateDialog.DrawText za pomocą FONT i SetBkMode w oknach Dialog

w proc dialogowym robię jakiś rysunek tekstu w WM_PAINT:

function DialogProc(hDlg: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall; 
... 
case Msg of 
    WM_PAINT: 
    begin 
     dc := BeginPaint(hDlg, ps);  
     bkmodePrev := SetBkMode(dc, TRANSPARENT); 
     hfnt := SendMessage(hDlg, WM_GETFONT, 0, 0); 
     hfntPrev := SelectObject(dc, hfnt); 
     DrawTextW(dc, 'Text', -1, R, DT_SINGLELINE or DT_CENTER or DT_VCENTER); 
     SelectObject(dc, hfntPrev); 
     // SetBkMode(dc, bkmodePrev); // do I need this? 
     EndPaint(hDlg, ps); 
     Result := True; 
    end; 
    end; 
... 

Teraz pytanie jest, robię to dobrze z czcionką, co oznacza, że ​​jest to właściwy sposób, aby uzyskać czcionki uchwyt okna dialogowego przy użyciu SendMessage(hDlg, WM_GETFONT, 0, 0) i przywrócenie go za pomocą SelectObject(dc, hfntPrev)? Czy muszę przywrócić stary BkMode z bkmodePrev przy użyciu SetBkMode(dc, bkmodePrev);? czy zrobi to dla mnie EndPaint?

P.S: Czy muszę zwolnić DC?

Odpowiedz

5

Czy robię to dobrze z czcionką?

Tak.

Czy muszę przywrócić starą BkMode z bkmodeprev wykorzystaniem SetBkMode(dc, bkmodeprev), czy będzie EndPaint to dla mnie zrobić?

nie przywróci trybu mieszania w tle. Ale EndPaint niszczy kontekst urządzenia, więc nie trzeba go przywracać. Jednak moim zdaniem najlepszą praktyką jest przywrócenie trybu mieszania w tle za każdym razem, gdy go zmienisz. Jeśli rozszerzysz kod w przyszłości, nie będziesz zaskoczony. Ale to naprawdę jest preferencja. Możesz przyjąć inną postawę.

Czy muszę zwolnić DC?

Nie, wystarczy połączenie z numerem EndPaint.


chciałbym napisać to tak:

dc := BeginPaint(hDlg, ps);  
bkmodeprev := SetBkMode(dc, TRANSPARENT); 
hfnt := SendMessage(hDlg, WM_GETFONT, 0, 0); 
hfntPrev := SelectObject(dc, hfnt); 
DrawTextW(dc, 'Text', -1, R, DT_SINGLELINE or DT_CENTER or DT_VCENTER); 
SelectObject(dc, hfntPrev); 
SetBkMode(dc, bkmodeprev); 
EndPaint(hDlg, ps); 

Choć można by argumentować, że byłoby lepiej, aby zawierać pewne sprawdzanie błędów.


Jak wskazano w uwagach należy podać wartość powrotną do wiadomości WM_PAINT. Z docs:

Jeśli procedura okno dialogowe przetwarza wiadomość o określonej wartości zwracanej, procedura okna dialogowego należy ustawić żądaną wartość zwracaną przez wywołanie SetWindowLong (hwndDlg, DWL_MSGRESULT, lResult) bezpośrednio przed powrotem PRAWDA. Zauważ, że musisz wywołać SetWindowLong bezpośrednio przed zwróceniem PRAWDA; wykonanie tego wcześniej może spowodować nadpisanie wartości DWL_MSGRESULT za pomocą zagnieżdżonego komunikatu okna dialogowego.

+1

dziękuję David. jak zwykle twoje odpowiedzi są złote :) – kobik

+2

EndPaint zniszczy kontekst urządzenia powodując, że tryb tła będzie ustawiony domyślnie (OPAQUE) na następną rundę. Nie ma potrzeby przywracania, tylko "klasa" i "prywatne" DC zachowują stan. –

+2

Ponieważ przetwarza 'WM_PAINT' w oknie dialogowym, potrzebuje' SetWindowLongPtr (hDlg, DWLP_MSGRESYLT, (LONG_PTR) 0); 'po wywołaniu' EndPaint'.Dopiero wtedy może zwrócić "PRAWDA", a może źle? – AlwaysLearningNewStuff