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

时间:2014-11-07 16:32:46

标签: c++ delphi winapi dialog

我正在使用CreateDialog创建一个Dialog。

在对话框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;
...

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

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

1 个答案:

答案 0 :(得分: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);

尽管如此,有人可能会认为最好包含一些错误检查。


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

  

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