【问题标题】:DrawText using FONT and SetBkMode in windows DialogDrawText 在 windows 对话框中使用 FONT 和 SetBkMode
【发布时间】:2015-01-04 12:18:57
【问题描述】:

我正在使用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 吗?

【问题讨论】:

    标签: c++ delphi winapi dialog


    【解决方案1】:

    我的字体做得对吗?

    是的。

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

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


    正如 cmets 中所指出的,您需要为 WM_PAINT 消息提供返回值。来自docs:

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

    【讨论】:

    • EndPaint 将破坏设备上下文,导致下一轮默认背景模式(不透明)。无需恢复,只有“类”和“私有”DC 保留状态。
    • 由于他在对话框中处理WM_PAINT,所以在EndPaint调用后需要SetWindowLongPtr( hDlg, DWLP_MSGRESYLT, (LONG_PTR)0 );。只有这样他才能返回TRUE 还是我错了?
    • @SertacAkyuz,所以我不需要恢复bkmodePrev?
    • @SertacAkyuz,恢复BkMode会有什么不好的影响吗?还是我应该简单地忽略它而不恢复它,把它留给EndPaint?
    • @David,在这种情况下,我应该像提到的 AlwaysLearningNewStuff 那样打电话给 SetWindowLongPtr( hDlg, DWLP_MSGRESYLT, (LONG_PTR)0 ); 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多