在Windows对话框中使用FONT和SetBkMode绘制文本

kob*_*bik 5 c++ delphi winapi dialog

我正在创建一个Dialog CreateDialog.

在对话框proc中我做了一些文字绘图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;
...
Run Code Online (Sandbox Code Playgroud)

现在的问题是,我是否正确使用字体,这意味着,这是使用SendMessage(hDlg, WM_GETFONT, 0, 0)和恢复对话框的字体句柄的正确方法SelectObject(dc, hfntPrev吗?我是否需要恢复旧的BkMode bkmodePrev使用SetBkMode(dc, bkmodePrev);?或者会EndPaint为我做那件事?

PS:我需要发布DC吗?

Dav*_*nan 5

我用字体做得对吗?

是.

我是否需要使用SetBkMode(dc, bkmodeprev)或恢复bkmodeprev的旧BkMode EndPaint

EndPaint不会为您恢复背景混合模式.但是EndPaint会破坏设备上下文,因此不需要恢复.但是,在我看来,最佳做法是在您更改后恢复背景混合模式.然后,如果您将来扩展代码,您将不会感到惊讶.但这确实是一种偏好.你可以采取不同的立场.

我需要释放DC吗?

不,呼吁EndPaint足够了.


我会像这样写:

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);
Run Code Online (Sandbox Code Playgroud)

虽然,有人可能会认为包含一些错误检查会更好.


正如评论中指出的那样,您需要为WM_PAINT消息提供返回值.来自文档:

如果对话框过程处理需要特定返回值的消息,则对话框过程应通过在返回TRUE之前立即调用SetWindowLong(hwndDlg,DWL_MSGRESULT,lResult)来设置所需的返回值.请注意,您必须在返回TRUE之前立即调用SetWindowLong; 提前执行此操作可能会导致DWL_MSGRESULT值被嵌套的对话框消息覆盖.

  • EndPaint将破坏设备上下文,导致后续模式的默认背景模式(OPAQUE).没有必要恢复,只有"阶级"和"私人"DC保留状态. (2认同)
  • 由于他在对话框中处理`WM_PAINT`,他需要`SetWindowLongPtr(hDlg,DWLP_MSGRESYLT,(LONG_PTR)0);`在`EndPaint`调用之后.只有这样他才能回归"真"或者说我错了吗? (2认同)