关于对话框窗口过程返回值
有时候,很多朋友会对对话框窗口过程(Dialog Procedure)的返回值感到疑惑,今天我试着使用一种不同的方法来给大家”翻译翻译”。
对话框过程实际上需要向操作系统返回两种信息:
1) 这个消息是否已经得到了处理?
2) 如果得到了处理,返回值应该是什么?
因为在传统的C语言中,一个函数只能返回一个值,但是在对话框窗口过程中需要返回上述提到的两种信息,那咋办?需要想出一种方法来返回这两种信息。
方法如下
对话框窗口过程的返回值表明了消息是否得到了处理。第二条信息,关于返回值应该是什么则会在存储在DWLP_MSGRESULT消息中。
换句话说,系统实现的默认对话框过程DefDlgProc,会看起来像如下这样:
![dc4868da25d018f6a44b636b7c42bbff.png](https://i-blog.csdnimg.cn/blog_migrate/7730db20789bf14658a7ab05f4bb3a6a.jpeg)
如果你返回任何非0值,则通过SetWindowLongPtr(hdlg, DWLP_MSGRESULT, value)设置的值将作为消息的处理结果值。
举个例子,许多WM_NOTIFY消息处理函数可以用来被重写为返回TRUE。如果希望一个列表视图(ListView)的标签取消编辑,则可以在LVN_BEGINLABELEDIT消息处理函数中返回TRUE。但是如果你在一个对话框窗口过程中这样做,则你需要分两步来这样做,思路如下:SetWindowLongPtr(hdlg, DWLP_MSGRESULT, TRUE);return TRUE;
上面代码中的第二行为对话框窗口过程设置了一个返回值TRUE,这就相当于告诉DefDlgProc,这个消息已经得到了处理,所以不需要系统再进行默认的消息处理了。而第一行告诉DefDlgProc,向消息的发送者(这里是列表视图控件)返回TRUE。如果你忘记这样做,则你希望返回的值可能不会被列表视图控件收到。
另外需要注意的地方是,DefDlgProc会在发送消息消息之前将DWLP_MSGRESULT设置为0,所以,如果对话框窗口过程忘记设置它,则消息处理的结果会为0。
基于上面的分析,从对话框窗口过程函数返回之前调用SetWindowLongPtr是非常重要的。如果你在设置DWLP_MSGRESULT值和返回TRUE之前做了其他的操作,则可能会触发某一条消息发送给窗口过程,就会导致消息的处理结果恢复为默认的0。
一些注意的地方
还有一小部分的特殊消息没有遵循上面的原则,具体可以参考DialogProc的帮助文档。为什么会有这些例外存在呢?
因为在最初设计对话框管理器(Dialog Manager)时,设计者认为对这些特殊的消息进行特殊的处理,可以使得对话框窗口过程更加容易编写,因为你可能不希望在从窗口过程返回时还需要额外的设置一下DWLP_MSGRESULT。幸运的是,从那个时候开始,后面没有人在添加新的例外消息了。
毕竟,比起不需要再编写SetWindowLongPtr(hdlg, DWLP_MSGRESULT, desiredResult),记住这些例外的消息心理负担可难多了。
![2430d5be980e2572fcee0cd511e5622b.png](https://i-blog.csdnimg.cn/blog_migrate/2f632610588fc5f689efa53ed7fc09c4.jpeg)