IDE:Eclipse Juno;编译器:MinGW 4.6.2;项目:Win32
我有一个带有两个有点不同的 MDI 子窗口的MainWindow : MdiChildWindowA和MdiChildWindowB。第三个子窗口SharedWindow不是 MDI,但可以由任一 MDI 子窗口使用。所有这些都封装在它们自己的 C++ 类中。
为了避免SharedWindow的扩散,我借用了单例设计的一部分:MainWindowClass::GetSharedWindowInstance()
将返回一个指向SharedWindow实例的指针,如果不存在则创建一个。 MainWindow.h
包括SharedWindow* pSharedWindow
备份功能。(这与SharedWindow成为单身人士一样接近。)
当MainWindow实例化MdiChildWindowA和MdiChildWindowB时,它传递this
给它们的构造函数,它们保存在类变量中pMainWindow
(定义为MainWindow*
和MdiChildWindowA.h
)MdiChildWindowB.h
。
cout
MainWindowthis
中的 of匹配MDI子窗口构造函数中的 ,但是当另一个函数调用时,已经改变了!制作静态似乎已经解决了问题,但如何改变?cout
pMainWindow
pMainWindow->GetSharedWindowInstance()
pMainWindow
pMainWindow
pMainWindow
同样,我发现HMODULE
andLPPICTURE
变量在 in 中是静态的,SharedWindow.h
否则它们会忘记它们在SharedWindow.cpp
. 指针类型是否以某种方式免于作为类变量的持久性? 我认为static
这是为了确保其类的所有实例都具有一个值。
编辑 2013-Sep-04:
下面是我的Application.cpp
(大部分是从教程中复制的)。我以为我的MainWindow
实例是在堆上创建的,并且会一直持续到退出。
#include "MainWindow.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow )
{ MSG msg;
HWND hMdiClientWindow;
MainWindow *winMain = new MainWindow( hInstance );
if( !winMain->Run( nCmdShow ) )
{ delete winMain;
return 1;
}
hMdiClientWindow = winMain->GetMdiClientWindow();
while( GetMessage( &msg, NULL, 0, 0 ) )
{ if( ! TranslateMDISysAccel( hMdiClientWindow, &msg ) )
{ TranslateMessage( &msg );
DispatchMessage ( &msg );
}
}
delete winMain;
return msg.wParam;
}
new MainWindow(...)
调用MainWindow::MainWindow()
,其中cout
显示this
是0xdd13a0。
MainWindow是在对 的调用中创建的Run(...)
,它将指针传递给MainWindow
in的实例lpParam
:
bool MainWindow::Run( int nCmdShow )
{ ...
hMainWindow = CreateWindowEx( ..., this );
...
}
在窗口过程中,指针保存在MainWindow的实例数据中:
LRESULT CALLBACK MainWindow::MainWindowProcedure( HWND hMainWindow, UINT Msg, WPARAM wParam, LPARAM lParam )
{ MainWindow* pThis;
if( Msg == WM_NCCREATE )
{ CREATESTRUCT* pCreateStruct = (CREATESTRUCT*) lParam;
pThis = (MainWindow*) pCreateStruct->lpCreateParams;
SetWindowLongPtr( hMainWindow, GWL_USERDATA, (LONG) pThis );
} else
{ pThis = (MainWindow*) GetWindowLongPtr( hMainWindow, GWL_USERDATA );
}
在中,当它被传递给MdiChildWindowA和MdiChildWindowBWM_CREATE
的构造函数时,cout
显示pThis
为0xdd13a0:
switch( Msg )
{ ...
case WM_CREATE:
{ unique_ptr<MdiChildWindowA> upMdiChildWindowA;
unique_ptr<MdiChildWindowB> upMdiChildWindowB;
...
up_MdiChildWindowA = unique_ptr<MdiChildWindowA>( new MdiChildWindowA( m_hInstance, pThis, [window dimensions] ) );
up_MdiChildWindowB = unique_ptr<MdiChildWindowB>( new MdiChildWindowB( m_hInstance, pThis, [window dimensions] ) );
MDI 子窗口的构造函数MainWindow
将参数中的指针复制pMainWindow
到类变量m_pMainWindow
中,并cout
显示两者都包含0xdd13a0:
MdiChildWindowA::MdiChildWindowA( HINSTANCE hInstance, MainWindow* pMainWindow, ... )
{ m_pMainWindow = pMainWindow;
....
}
在WM_CREATE
MDI 子窗口程序中,cout
显示m_pMainWindow
仍包含0xdd13a0。唯一的其他引用m_pMainWindow
发生在WM_LBUTTONDBLCLICK
哪里,除非我将其设为静态,否则它会以某种方式变为0xdd1380(可能在传递过程中DefMDIChildProc(...)
?):
MdiChildWindowA::MdiChildWindowProcedure( ... )
{ ...
switch( ... )
{ ...
case WM_LBUTTONDBLCLICK:
{ SharedWindow* pSharedWindow;
...
pSharedWindow = pThis->m_pMainWindow->GetInstanceOfSharedWindow(); // pThis points to this instance of MdiChildWindowA. cout confirms its value hasn't changed.
由于m_pMainWindow
指向错误的地方,当SharedWindow
通过 调用函数时程序崩溃pSharedWindow
。然而,它似乎GetInstanceOfSharedWindow()
存在于这个虚假实例中,MainWindow
因为返回了一个地址 - 但是,在上面的代码中,它是MdiChildWindowA
!
(注意:我的命名约定让人抓狂,所以我用不太危险的名字重新输入了代码。希望没有错别字。)
@brunocodutra,@Chris Hayes:我还没有足够的评论意见,但我很欣赏你的想法。