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

DrawText using FONT and SetBkMode in windows Dialog

本文关键字:SetBkMode 绘制 文本 FONT windows 对话框      更新时间:2023-10-16

我正在使用CreateDialog创建一个对话框。

在对话框过程中,我在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;
...

现在的问题是,我对字体做得对吗?也就是说,这是使用SendMessage(hDlg, WM_GETFONT, 0, 0)获得对话框的字体句柄并使用SelectObject(dc, hfntPrev恢复对话框的正确方法吗?是否需要使用SetBkMode(dc, bkmodePrev);恢复bkmodePrev的旧BkMode?还是EndPaint会为我做这件事?

p.S:我需要释放DC吗?

我的字体做得对吗?

是的。

我需要使用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);

尽管如此,有人可能会争辩说,最好包括一些错误检查。


正如注释中所指出的,您需要为WM_PAINT消息提供一个返回值。来自文档:

如果对话框过程处理需要特定返回值的消息,则对话框过程应在返回TRUE之前立即调用SetWindowLong(hwndDlg、DWL_MSGRESULT、lResult)来设置所需的返回值。请注意,在返回TRUE之前,必须立即调用SetWindowLong;较早这样做可能导致DWL_MSGRESULT值被嵌套对话框消息覆盖。