这是一个非常有趣的功能:在Widows中,是可以把子窗口在子线程中实例化并打开进行操作的,实现了子窗口的所有的操作,包括提示,都不会与主窗口和其它的子窗口产生影响,就像是一个独立的进程一样。
右边的主窗口中打开有多个会话实例窗口,同时每个窗口都在实时的接收不同的数据;左边有两个子窗口,一个在实时的下载文件,另一个窗口在操作时,完全不会影响到其它的窗口的运行。
其实,这是一个很让人奇怪的实现,在此之前,曾试过用.net来尝试,结果好像是不行,但当我在实现VxTerm的过程中,竟然发现C++ 中的MFC框架上,竟然是支持这样的窗口方式,这会造成一个奇怪的现象:
左边的那几个窗口实际上是在子线程中运行的,但鼠标和键盘在它们上的操作时,实际上是通过主线程去给它们发送消息的。
事实是,当我试着这么实现后,发现它的运行竟然是稳定的,不会崩溃!
而如果我们不这么去实现的话,除非是用多进程实例的方式去实现,否则窗口的modal提示之间是会互相影响,导致窗口之间的zorder、循环消息等就会互相影响。
比如,当我一开始我没有这么去实现这个子线程中的窗口时,当子窗口中有一个modal提示时,其它窗口就没法正常的响应鼠标、键盘的操作了。
而当我尝试着实现了这么一个子线程里的窗口后,一切都变得美好了,所有窗口之间的操作、提示都互不影响,非常完美!
实现方式:采用CWinThread实现
先写一个xCThreadForSftpFrm,我们需要用它来实例化一个子线程,同时把窗口的参数传递到这
个子线程中,在子线程开始运行后,由这个子线程来实例化一个窗口。
#pragma once
// xCThreadForSftpFrm
class xCThreadForSftpFrm : public CWinThread
{
DECLARE_DYNCREATE(xCThreadForSftpFrm)
protected:
xCThreadForSftpFrm();
virtual ~xCThreadForSftpFrm();
int xWidth, xHeight;
CWnd* xParent = 0;
CString xIP;
UINT xPort;
string xUsername;
string xPassword;
CString xTitle;
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
protected:
DECLARE_MESSAGE_MAP()
afx_msg void xExit(WPARAM wParam, LPARAM lParam);
public:
xCThreadForSftpFrm(CWnd* xParent
, const CString& xIP, const UINT& xPort, const string& xUsername, const string& xPassword, const CString& xTitle
, const int& xWidth, const int& xHeight
);
};
在xCThreadForSftpFrm的InitInstance里,实例化一个已定义好的dialog,同时,必须要
return TRUE; //返回真,否则线程将会被中止退出。
BOOL xCThreadForSftpFrm::InitInstance()
{
xFrmSftp * f=new xFrmSftp(this, xParent,xIP
, xPort
,xUsername
, xPassword);
f->xTitle =xTitle;
f->Create(IDD_xFrmSftp);
f->SetWindowPos(NULL, 0, 0, xWidth * 0.8, xHeight * 0.8, SWP_NOZORDER );
f->ShowWindow(SW_SHOW);
return TRUE;
}
调用的时候:
//一定要通过指针方式实例化这一个子线程类,这将会让它可以在当前过程结束后,变量t中的实例不会被清理回收
xCThreadForSftpFrm* t = new xCThreadForSftpFrm(
this, IP()
, Port()
, UserName_s()
, Password
, L"sftp>会话名称"
, xWidth, xHeight
)
;
t->m_bAutoDelete = 1; //需要在后面的子窗口关闭后,做出子线程结束的操作,子线程就能自动被清理,否则会出现内存泄漏
t->CreateThread(); //开始吧。
xCThreadForSftpFrm中还需要接收窗口的关闭消息,然后通过AfxEndThread(0);结束当前线程
void xCThreadForSftpFrm::xExit(WPARAM wParam, LPARAM lParam)
{
ExitInstance();
AfxEndThread(0);
}
最终实现的效果,可以下载VxTerm,然后打开sftp就可以看到。