使用 WINAPI 示例对话框中的属性表(不使用 MFC)
谁能给我指出一个使用 WINAPI(而不是 MFC)在对话框中嵌入属性表的 WINAPI 示例?
Can anyone point me at an WINAPI example of embedding a property sheet in a dialog box using WINAPI (not MFC)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
作为记录,以下是我在学习过程中学到的一些东西
调查这个问题。我从这里获得了大部分/所有这些
在这里提问或通过搜索网络提问。感谢大家的
你的帮助!
我编写了一个类来封装我发现的所有内容;
如果有兴趣获取副本,请发送电子邮件[电子邮件受保护]。
将父窗口的 HWND 传递给属性表
创建属性表时 PROPSHEETHEADER 的 .hwndParent
与PropertySheet页面功能。
我在对话框上使用了图片控件作为属性的父级
这就是我用作 hwndParent 的 HWND。
使用回调更改属性表的样式
标头中的 pfnCallback 字段,不要忘记包含
dwFlags 中的 PSH_USECALLBACK。请参阅 PropSheetProc 函数
MSDN。在回调的 PSCB_PRECREATE 处理程序中,
通过删除来调整属性表的窗口样式
WS_POPUP 并添加 WS_CHILD。我不需要边框或标题
属性表上的栏,所以我还删除了 WS_CAPTION、WS_SYSEMNU,
& DS_MODALFRAME
使用子窗口而不是弹出窗口巧妙地解决了
一些问题,例如当父级时移动属性表
移动,正确保持父窗口的蓝色/灰色状态
颜色和剪裁问题。也就是说,您不必担心这些事情。
如果你停在这里,你会面临另一个问题。对话框支持
WIN32 中的代码会进入 cpu 循环,尝试查找属性表并
其 Windows 中的控件。请参阅
WS_EX_CONTROLPARENT 和 DS_CONTROL 的用途是什么?
一个很好的解释
这个问题。解决方案是添加 WS_EX_CONTROLPARENT 扩展
属性表的样式。你可以找到这方面的信息
在网络上搜索 WS_EX_CONTROLPARENT。 你找不到的东西
给我带来了很大的悲伤。如果您使用对话框上的控件作为
父级,您还必须设置其 WS_EX_CONTROLPARENT。
我不知道 WS_EX_CONTROLPARENT 和 DS_CONTROL 之间有什么区别,也不知道您是否可以用 DS_CONTROL 替换 WS_EX_CONTROLPARENT。从网上我了解到 DS_CONTROL 与选项卡有关。我的测试应用程序对于带或不带 DS_CONTROL 的选项卡的工作方式相同。
我在调用后处理了 WS_EX_CONTROLPARENT 事务
PropertySheet 函数用于创建属性表。我不知道
是否可以在回调例程中执行此操作。我想
您可以在回调中使用 GetParent 来获取 HWND
控制。
使用 PropertySheet 函数创建属性表后,
你必须正确定位它:
我允许边框有几个像素。
如果您想删除所有属性表按钮及其占用的空间:
可以删除单个按钮:
您可以使用 PSH_NOAPPLYNOW 删除 APPLY 按钮
创建属性表时,PROPERTYSHEETHEADER 中的 dwFlags 。
直到用户首先创建属性表页面
激活它们。我希望它们全部在财产被创建时创建
工作表已创建。
有一个 PROPSHEETPAGE 标志可以做同样的事情(来自 MSDN)
但我担心4.71版本的业务,所以我自己做了。
您可以更改任何按钮上的文本:
之一,
其中 ButtonID 是 IDOK IDCANCEL IDHELP IDAPPLYNOW IDAPPLYNOW 在我的系统上未定义
因此以下是我打算如何使用属性表。我将把所有的初始化和
包含属性表的对话框中的终止代码并消除所有属性表按钮。我可以在那里设置所有初始值,并在用户按下某个 DO IT 按钮时检索所有最终值。我注意到,设置文本框等操作会导致包含页面对话框获得 WM_COMMAND/EN_CHANGE。如果您使用此消息启用“应用”按钮,则可能需要在设置任何列表框后禁用页面的更改标志。我通过在设置初始值后清除所有更改的标志解决了这个问题。 (我怀疑在发送所有 INIDIALOG 消息后,属性表会清除已更改的标志。无论如何,如果在 INIDIALOG 处理程序页面中设置了文本框,则不会启用 APPLY。)如果发现错误,我将选择该属性表页面并在父对话框中放置一些红色文本来描述错误。属性表对话框程序唯一需要做的就是操作它们的控件。
让我困惑的事情之一是如何确定所有页面是否都从其 WS_NOTIFY/PSN_APPLY 消息返回 PSNRET_NOERROR。我已经取得了一些成功
当报告 PSNRET_INVALID 或收到 PSN_KILLACTIVE 时,连续 PSNRET_NOERROR 回复的数量将计数设置为零。如果计数达到属性表标题中的页数,我假设所有页面都返回 PSNRET_NOERROR。但我担心诸如禁用页面和不可见页面之类的事情。
For the record, here are some of the things I learned while
investigating this question. I obtained most/all of this from
asking questions here or by searching the web. Thanks to all for
your help!
I have written a class to encapsulate everything I've discovered;
if interested in getting a copy send me an email [email protected].
Pass the HWND of the parent window for your property sheet in
.hwndParent of the PROPSHEETHEADER when creating the property sheet
with the PropertySheet page function.
I used a picture control on the dialog as the parent of the property
sheet so that's the HWND I used as the hwndParent.
Change the style of the property sheet using the call back
pfnCallback field in the header, don't forget to include
PSH_USECALLBACK in dwFlags. See PropSheetProc Function in
the MSDN. In the PSCB_PRECREATE handler of the callback,
adjust the window style of the property sheet by removing
WS_POPUP and adding WS_CHILD. I did not want a border or title
bar on the property sheet so I also removed WS_CAPTION, WS_SYSEMNU,
& DS_MODALFRAME
Using a child window instead of a popup window neatly solves
some problems such as moving the property sheet when the parent
moves, keeping the blue/gray state of the parent window properly
colored, and clipping issues. I.e. you don't have to worry about these things.
If you stopped here, you'd face another problem. The dialog support
code in WIN32 would get in a cpu loop trying to find the property sheet and
controls in its Windows. See
What is WS_EX_CONTROLPARENT and DS_CONTROL For?
for a pretty good explanation of
this problem. The solution is to add the WS_EX_CONTROLPARENT extended
style to the property sheet. You can find information on this
on the web by searching for WS_EX_CONTROLPARENT. What you won't find
caused me much grief. If you use a control on the dialog as the
parent, you must also set its WS_EX_CONTROLPARENT.
I do not know what the difference between WS_EX_CONTROLPARENT and DS_CONTROL is nor do I know if you could substitute DS_CONTROL for WS_EX_CONTROLPARENT. From the web I gather that DS_CONTROL has something to do with tabs. My test app works the same with respect to tabs with or without DS_CONTROL.
I took care of the WS_EX_CONTROLPARENT business after calling the
PropertySheet function to create the property sheet. I do not know
if you could do this in the call back routine or not. I suppose
you could use GetParent in the call back to get the HWND of the
control.
After creating the property sheet with the PropertySheet function,
you have to position it properly:
I allowed a couple of pixels for the border.
If you want to get rid of all the property sheet buttons and the space they take:
Individual buttons can be eliminated:
You can get rid of the APPLY button using the PSH_NOAPPLYNOW
dwFlags in the PROPERTYSHEETHEADER when you create the property sheet.
The property sheet pages will NOT be created until the user first
activates them. I wanted them all to be created when the property
sheet was created.
There's a PROPSHEETPAGE flag that does the same thing (from the MSDN)
But I was worried about the Version 4.71 business so I did it myself.
You can change the text on any of the buttons:
where ButtonID is one of IDOK IDCANCEL IDHELP IDAPPLYNOW
IDAPPLYNOW is undefined on my system so
Here's how I intend to use my property sheet. I'm going to put all the initialization and
termination code in the dialog containing the property sheet and eliminate all the property sheet buttons. I can set all the initial values there and retrieve all the final values there when the user pushes some DO IT button. I notice that the act of setting, for example, a text box causes the containing page dialog to get a WM_COMMAND/EN_CHANGE. If you use this message to enable the APPLY button, you may need to disable the change flag for the page after setting any list boxes. I solved this problem by clearing all the changed flags after setting the initial value. (I suspect the property sheet clears the changed flag after all the INITDIALOG messages have been sent. In any case APPLY is not enabled if the text boxes are set in the page INITDIALOG handlers.) If I find an error I will select that property sheet page and put some red text in the parent dialog describing the error. The only thing the property sheet dialog procedures need to do is manipulate their controls.
One of the things that puzzles me is how to determine if all pages have returned PSNRET_NOERROR from their WS_NOTIFY/PSN_APPLY messages. I've had some success counting the
number of successive PSNRET_NOERROR replies setting the count to zero when a PSNRET_INVALID is reported or a PSN_KILLACTIVE is received. If the count reaches the number of pages in the property sheet header, I assume all pages have returned PSNRET_NOERROR. But I worry about things like disabled and invisible pages.