C++ 中的哪个 Windows API 将帮助我识别当前 ComboBox 正在使用哪个对话框类?
Posted
技术标签:
【中文标题】C++ 中的哪个 Windows API 将帮助我识别当前 ComboBox 正在使用哪个对话框类?【英文标题】:Which Windows API in C++ will help me in identifying which Dialog Class the Current ComboBox is using? 【发布时间】:2019-08-23 17:40:23 【问题描述】:我如何知道特定组合框正在使用哪种对话框样式?是否有任何 Win32 API 可以为我提供这些信息?
我将CDialog
用于一些组合框,CDialogEx
用于一些组合框,以及一个内部对话框类,比如说Ctl3dDialogEx
,用于其他组合框。 GetClassName()
将返回 ComboBox 的类名(如果我正在传递 ComboBox 处理程序),可以是 "CComboBox"
。
是否有任何 Win32 API,我将传递 ComboBox 处理程序并将其返回给我 Dialog 类名称,例如:"CDialog"
、"CDialogEx"
、"Ctl3dDialogEx"
等?
以下代码可能有助于理解:
void ComboBox_DoSomeManipulation( HWND hldg , int n )
/*"hldg" is the handler of the Current ComBobox */
LPTSTR lpClassName;
int nMaxCount = 256;
/*This will return "CComboBox" as value in lpClassName */
GetClassName(hldg , lpClassName , _count_of(nMaxCount));
/*Is there any WIN API like above which can give */
/* Dialog class information like CDialog, CDialogEx */
/* which the ComboBox is using ? */
【问题讨论】:
所有对话框与documented共享相同的类名#32770
。
我有一个合理的答案,然后它被关闭了——过早的。我想我理解这个问题。
他希望能够获得 CRuntimeClass*,Win API 在这里无济于事,因为所有对话框都是 DIALOG 类(#32770),正如@IInspectable 所指出的那样。
@JosephWillcoxson 如果您有任何建议,请提供帮助,我再次重新定义了问题。
请注意,GetClassName(hldg , lpClassName , _count_of(nMaxCount));
将失败,如图所示。没有为lpClassName
分配内存,_count_of()
需要一个固定数组作为输入,而不是整数。
【参考方案1】:
如果您的组合框能以某种方式获得指向其父窗口的正版指针,那么您可以使用dynamic_cast<CDialogEx*>(pParent)
来查看它是否为CDialogEx
(如果不是则返回nullptr
) .您将需要几个单独的检查,从最派生的类开始!所以,如果你的Ctl3dDialogEx
派生自CDialogEx
,那么:
. . .
CWnd *pParent = pCombo->GetParent(); // This, as is, is not valid code!
if (dynamic_cast<Ctl3dDialogEx*>(pParent) != nullptr)
// It's a Ctl3dDialogEx parent
else if (dynamic_cast<CDialogEx*>(pParent) != nullptr)
// It's a CDialogEx
else // Assuming no other options …
// It's a CDialog
如果可以的话,我建议在初始化期间制作父窗口的this
指针的可访问(静态?)副本。但是还有其他方法……
例如,假设您可以控制ComboBox_DoSomeManipulation
的定义,并且在调用它时,将第一个参数从HWND
更改为CWnd*
,并且在调用它时使用this
而不是@ 987654332@。 (但这取决于你的代码结构!)
【讨论】:
@Joseph Willcoxson 这与RUNTIME_CLASS(CDialogEx)
调用的比较“相似”,但恕我直言,更简单、更标准。
我现在编辑了我的答案,因为我误解了CWnd::FromHandlePermanent
的工作原理!如果这真的通过系统HWND
对象列表运行并查看它们附加到的(如果有的话)容器类对象,那么这可能也会起作用!
CWnd::FromHandle() 将始终返回 CWnd*。如果它不在永久地图中,那么它将在临时地图中创建一个 CWnd*。如果您没有只有一个应用程序,或者正在使用所有扩展 DLL,那么如果混合使用扩展和 usr dll,您可能会得到意想不到的结果,例如在 MFC COM 服务器的情况下。您要确保使用相同的 MFC 实例(句柄映射、GetMessage() 循环等)。调用 CWnd::FromHandlePermanent() 可确保您使用的是相同的 MFC 实例。如果不是同一个 MFC 实例,它将返回 NULL。
感谢您的所有意见,非常感谢。我尝试使用 CWnd* pWnd = CWnd::FromHandlePermanent(hdlg);但这是返回 NULL 。所以我不能在那个指针上做任何 GetRuntimeClass() 。作为替代方案,我尝试使用 CWnd::FromHandle(hDlg) ,它确实返回了一个指针,所以当我执行 pWnd->GetRuntimeClass() 时,它向我显示“CComboBox”作为类名。所以我只是想知道我还能尝试什么。请注意,函数 ComboBox_DoSomeManipulation 位于非 MFC 代码库中。再次非常感谢迄今为止的所有投入
从你所说的看来,你函数中的hldg
参数似乎是组合框控件本身的HWND
,而不是父对话框的HWND
。但我仍然有点困惑为什么::FromHandlePermanent
返回NULL
但::FromHandle
给出RunTimeClass
的CComboBox
。也许 MFC 正在用 HWND
对象做一些“聪明”的事情?【参考方案2】:
没有 Windows API 帮助,因为所有这些对话框都是 Windows DIALOG 类的子类。如果这一切都在进行中,并且您使用的是同一个 MFC 实例,您也许可以这样做:
CWnd* pWnd = CWnd::FromHandlePermanent(hdlg);
if (pWnd != NULL)
if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialog))
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogEx))
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogxyz))
在过去,与 MFC 一起使用的 MS 编译器不能很好地与 dynamic_cast 配合使用,所以通常在使用 MFC 时,我不使用它。我可能应该更加信任它,但直到 2008 年我一直使用 Visual C++ 6,所以我可能有点厌倦了。更“标准”的“MFC方式”是使用MFC宏……
另一种可能的方式是:
if (CDialogxyz* pDlgxyz = DYNAMIC_DOWNCAST(CDialogxyz, pWnd))
else if (CDialogEx* pDlgEx = DYNAMIC_DOWNCAST(CDialogEx, pWnd))
else if (CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, pWnd))
【讨论】:
感谢您的所有意见,非常感谢。我尝试使用 CWnd* pWnd = CWnd::FromHandlePermanent(hdlg);但这是返回 NULL 。所以我不能在那个指针上做任何 GetRuntimeClass() 。作为替代方案,我尝试使用 CWnd::FromHandle(hDlg) ,它确实返回了一个指针,所以当我执行 pWnd->GetRuntimeClass() 时,它向我显示“CComboBox”作为类名。所以我只是想知道我还能尝试什么。请注意,函数 ComboBox_DoSomeManipulation 位于非 MFC 代码库中。再次非常感谢迄今为止的所有投入。以上是关于C++ 中的哪个 Windows API 将帮助我识别当前 ComboBox 正在使用哪个对话框类?的主要内容,如果未能解决你的问题,请参考以下文章
Windows C++ API:如何将整个二进制文件读入缓冲区?
Borland Builder C++ 6 中的 CoreAudio API