2014-11-07 8 views
5

Sto creando una finestra di dialogo utilizzando CreateDialog.DrawText utilizzando FONT e SetBkMode in Windows Dialog

nella finestra di proc faccio un po 'il disegno di testo in 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; 
... 

Ora la domanda è, sto facendo bene con il tipo di carattere, il che significa che, è questo il modo corretto per ottenere il tipo di carattere gestire una finestra di dialogo usando SendMessage(hDlg, WM_GETFONT, 0, 0) e ripristinandola con SelectObject(dc, hfntPrev)? Devo ripristinare il vecchio BkMode da bkmodePrev usando SetBkMode(dc, bkmodePrev);? o lo faranno EndPaint per me?

P.S: devo rilasciare la DC?

risposta

5

Sto facendo bene con il carattere?

Sì.

ho bisogno per ripristinare il vecchio BkMode di bkmodeprev usando SetBkMode(dc, bkmodeprev), o sarà EndPaint farlo per me?

EndPaint non ripristinerà la modalità di mix di sfondo per voi. Ma EndPaint distrugge il contesto del dispositivo in modo che non debba essere ripristinato. Tuttavia, a mio avviso, la procedura migliore è ripristinare la modalità mix di background ogni volta che la si modifica. Quindi se estendi il codice in futuro non sarai sorpreso. Ma questa è davvero una preferenza. Puoi prendere una posizione diversa.

Devo rilasciare la CC?

No, la chiamata a EndPaint sufficiente.


vorrei scrivere questo modo:

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); 

Anche se, si potrebbe sostenere che sarebbe meglio includere qualche controllo degli errori.


Come è fatto notare nei commenti è necessario fornire un valore di ritorno per il messaggio WM_PAINT. Dal docs:

Se la dialog box procedure elabora un messaggio che richiede un valore di ritorno specifica, la procedura della finestra di dialogo dovrebbe impostare il valore di ritorno desiderato chiamando SetWindowLong (hwndDlg, DWL_MSGRESULT, lResult) subito prima di ritornare TRUE. Si noti che è necessario chiamare SetWindowLong immediatamente prima di restituire TRUE; farlo prima potrebbe comportare la sovrascrittura del valore DWL_MSGRESULT da parte di un messaggio di una finestra di dialogo nidificata.

+1

grazie David. come al solito le tue risposte sono d'oro :) – kobik

+2

EndPaint distruggerà il contesto del dispositivo causando il default della modalità di sfondo (OPAQUE) per la prossima volta. Non è necessario eseguire il ripristino, solo i controller di dominio "classe" e "privato" mantengono lo stato. –

+2

Poiché sta elaborando 'WM_PAINT' in una finestra di dialogo, ha bisogno di' SetWindowLongPtr (hDlg, DWLP_MSGRESYLT, (LONG_PTR) 0); 'dopo la chiamata' EndPaint'.Solo allora può restituire "VERO" o forse ho sbagliato? – AlwaysLearningNewStuff