在哪里定义PAINTSTRUCT以及为什么要定义HDC?

时间:2014-02-07 16:20:17

标签: c++ winapi memory hdc

我的问题很简单,也不是很重要。

  1. 我开始学习编写Win32应用程序。当我从其他人那里阅读代码时,我经常看到他们将PAINTSTRUCT ps;放在WndProc中的switch语句之前。他们为什么不把这个问题放到WM_PAINT?他们为ps分配内存然后不使用它?

  2. 我总是看到PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps);。但我多次检查ps.hdc的值,ps.hdchdc的值每次都相等。定义hdc还有其他原因,而不仅仅是可读性还是编写更少的代码?

  3. (对不起,如果我的英语不好而且问题不属于这个社区的水平)

4 个答案:

答案 0 :(得分:5)

回答第1点:Win32 API是为C设计的(它已经很老了)将PAINTSTRUCT ps;放在case语句中需要放入case的内容在大括号{}内,因为C不允许内联声明。 C ++也可能在没有大括号的情况下在case语句中声明变量时出现问题 - 在不调用构造函数的情况下调用析构函数。您会很快发现switch() case...样式将难以维护,该功能将变得非常庞大且难以处理,并且与Intellisense等功能不相称。通常,您会看到开发人员使用地图将功能与特定消息相关联: -

WindowProc (args)
{
  func_ptr = some_map.GetValue (message_type)
  if func_ptr not null
    call func_ptr
  else
    DefWindowProc (args)
}

对于第2点,如果出现错误,hdc的值将为null,并且使用hdc代替ps.hdc看起来更干净。此外,hdc更容易传递给ps以外的其他功能。但除此之外,文档没有说明为什么ps.hdcBeginPaint的结果不同的原因。

答案 1 :(得分:2)

  

当我读取其他人的代码时,我经常看到他们把PAINTSTRUCT ps;在WndProc中的switch语句之前。为什么他们不把这个放入WM_PAINT?

几种可能性:

  1. 他们正在或正在使用较旧的C风格,其中所有局部变量都必须在函数的开头定义。
  2. 根据您的编译器及其警告级别,您可以在尝试在switch语句中的case中声明变量时收到警告。
  3. 他们只是马虎。
  4. 窗口程序可能不应该处理"消息,而是将它们分派给特定于消息的处理程序。因此,WndProc中的WM_PAINT情况应该调用一个单独的函数来执行绘制,而PAINTSTRUCT可以是该单独函数的本地函数。但我们正在冒险进入意见,所以我会把它留在那里。

      

    我总是看到PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps);

    我似乎记得有一个模糊的情况,返回的设备上下文句柄可能与PAINTSTRUCT中的不同,但可能非常罕见,在现代版本的Windows中可能不存在。

    考虑返回的HDC是一种方便。如果您的绘画很简单并且不需要PAINTSTRUCT中的任何其他字段,那么这将为您提供一种简单的方法来引用设备上下文。

答案 2 :(得分:1)

  1. 它确实没有区别,并且每次调用窗口过程时,许多实现都将“分配”内存,无论变量是在函数的顶部声明还是在WM_PAINT的情况下声明。开关。

  2. BeginPaint不仅仅是返回ps.hdc

答案 3 :(得分:1)

  

我经常看到他们将PAINTSTRUCT ps;放在WndProc中的switch语句之前。为什么他们不把这个问题放到WM_PAINT?他们为ps分配内存然后不使用它?

这样做是不好的做法。最佳做法是调用单独的函数来执行绘制,并避免使用页面长的窗口过程。但是如果你必须在窗口过程中绘制,请使用尽可能局部的范围声明变量。

  

定义hdc还有其他原因,而不仅仅是可读性还是编写更少的代码?

这是一种便利。由于绘制函数一次又一次地引用设备上下文,因此将它存储在局部变量中很方便,因此使代码更简洁。是的,当BeginPaint成功时,可以保证HDC返回的BeginPaint等于绘制结构中的HDC