对话框中使用WINAPI示例的属性表(不使用MFC)

对话框中使用WINAPI示例的属性表(不使用MFC),winapi,dialog,propertysheet,Winapi,Dialog,Propertysheet,有人能给我举一个使用WINAPI(不是MFC)在对话框中嵌入属性表的WINAPI示例吗?下面是我在 调查这个问题。我大部分[全部]都是从你那里得到的 在这里提问或通过搜索网页。谢谢大家的支持 你的帮助 我已经编写了一个类来封装我所发现的一切; 如果有兴趣获得副本,请给我发送电子邮件mdorl@wisc.edu. 在中传递属性页的父窗口的HWND 创建属性页时PROPSHEETHEADER的.hwndParent 使用PropertySheet页面功能 我使用对话框上的图片控件作为属性的父级 这就

有人能给我举一个使用WINAPI(不是MFC)在对话框中嵌入属性表的WINAPI示例吗?

下面是我在 调查这个问题。我大部分[全部]都是从你那里得到的 在这里提问或通过搜索网页。谢谢大家的支持 你的帮助

我已经编写了一个类来封装我所发现的一切; 如果有兴趣获得副本,请给我发送电子邮件mdorl@wisc.edu.

在中传递属性页的父窗口的HWND 创建属性页时PROPSHEETHEADER的.hwndParent 使用PropertySheet页面功能

我使用对话框上的图片控件作为属性的父级 这就是我用作hwndParent的HWND

使用回调更改属性页的样式 标题中的pfnCallback字段,不要忘记包括 PSH_在dwFlags中使用回调。请参阅中的PropSheetProc函数 MSDN。在回调的PSCB_预创建处理程序中, 通过删除来调整属性页的窗口样式 WS_弹出窗口并添加WS_子项。我不想要边界或头衔 所以我也删除了WS_标题,WS_SYSEMNU, &D_模态框架

LONG L = ((LPDLGTEMPLATE)lParam)->style;
L &= ~WS_POPUP; 
L &= ~WS_CAPTION;       // gets rid of title bar
L &= ~WS_SYSMENU;       
L &= ~DS_MODALFRAME;        // gets rid of border
L |=  WS_CHILD;         // 40000000
((LPDLGTEMPLATE)lParam)->style = L;
使用子窗口而不是弹出窗口可以很好地解决 一些问题,例如当父对象 移动,保持父窗口的蓝色/灰色状态 彩色和剪辑问题。也就是说,你不必担心这些事情

如果你停在这里,你将面临另一个问题。对话框支持 WIN32中的代码将进入cpu循环,试图查找属性表并 控件在其窗口中。看

为了一个很好的解释 这个问题。解决方案是添加WS_EX_CONTROLPARENT扩展 将样式添加到属性页。你可以找到这方面的信息 在web上搜索WS_EX_CONTROLPARENT你找不到的 这使我很伤心。如果使用对话框上的控件作为 父级,您还必须设置其WS_EX_CONTROLPARENT。

我不知道WS_EX_CONTROLPARENT和DS_CONTROL之间的区别是什么,也不知道您是否可以用DS_CONTROL代替WS_EX_CONTROLPARENT。从网上我得知DS_控件与选项卡有关。我的测试应用程序在带有或不带有DS_控件的选项卡上的工作方式相同

我打电话给公司后负责了WS_EX_CONTROLPARENT业务 PropertySheet函数创建属性表。我不知道 是否可以在回拨程序中执行此操作。我想 您可以在回调中使用GetParent来获取 控制

使用PropertySheet函数创建属性表后, 您必须将其正确定位:

SetWindowPos(hwndPS, HWND_TOP, 2, 2, -1, -1,
             SWP_NOSIZE | SWP_NOACTIVATE); 
我允许边界有几个像素

如果要删除所有属性页按钮及其占用的空间,请执行以下操作:

RECT rectWnd;
RECT rectButton;

GetWindowRect(hwndPS, &rectWnd);
HWND hWnd = ::GetDlgItem(hwndPS, IDOK);

if(!hWnd)
{
    DebugBreak();
}

GetWindowRect(hWnd, &rectButton);

SetWindowPos (hwndPS, NULL, 0, 0,
          rectWnd.right - rectWnd.left, rectButton.top - rectWnd.top,
          SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
可以取消单个按钮:

hwndOk = GetDlgItem (hwndPS,IDOK);              // Hide the OK button
ShowWindow (hwndOk, SW_HIDE);
EnableWindow (hwndOk, FALSE);
您可以使用PSH_NOAPPLYNOW摆脱应用按钮 创建属性表时,属性表中的dwFlags

只有在用户首先创建属性页时,才会创建属性页 激活它们。我希望他们都被创建时,财产 工作表已创建

unsigned int iP;
for (iP=0; iP<Header.nPages; iP++)
{
    if (iP != Header.nStartPage)
        SendMessage (hwndPS, PSM_SETCURSEL,iP,NULL);
}
SendMessage (hwndPS, PSM_SETCURSEL,Header.nStartPage,NULL);
其中ButtonID是IDOK IDCANCEL IDHELP IDAPPLYNOW之一

IDAPPLYNOW在我的系统中未定义,所以

#define IDAPPLYNOW     0x3021   
以下是我打算如何使用我的财产清单。我要把所有的初始化和 包含属性页的对话框中的终止代码,并删除所有属性页按钮。我可以在那里设置所有初始值,并在用户按下一些DoIt按钮时检索所有最终值。我注意到设置的行为,例如,一个文本框导致包含页面的对话框得到一个WM_命令/EN_更改。如果使用此消息启用应用按钮,则在设置任何列表框后,可能需要禁用页面的更改标志。我通过在设置初始值后清除所有更改的标志来解决这个问题。(我怀疑在发送所有INITDIALOG消息后,属性页会清除changed标志。在任何情况下,如果在页面INITDIALOG处理程序中设置了文本框,则不会启用APPLY。)如果发现错误,我将选择该属性页,并在父对话框中放置一些描述错误的红色文本。属性表对话框过程需要做的唯一一件事就是操纵它们的控件

困扰我的一件事是如何确定是否所有页面都从其WS\u NOTIFY/PSN\u APPLY消息返回了PSNRET\u NOERROR。我算了一些成功的数字 当报告PSNRET_无效或接收到PSN_无效时,将计数设置为零的连续PSNRET_NOERROR回复数。如果计数达到属性表标题中的页数,我假设所有页面都返回PSNRET_NOERROR。但我担心的是诸如禁用和不可见页面之类的事情

SetDlgItemText (hwndPS,ButtonID,Text);
#define IDAPPLYNOW     0x3021