远程控制编程中多窗口实现

 

远程控制软件中窗口管理主要有两种模式,一种是以灰鸽子远控为代表的单窗口单任务管理模式,一种是以黑洞远控为代表的多窗口多任务管理模式。前一种比较简单,本文讲第二种方案的实现。这里着重讲窗口多开,多任务另起篇幅讲述。

假如我们需要同时对3台远程主机进行文件管理,那么需要打开3个文件管理的对话框,这3个对话框相同的是什么?不同的又是什么?相同的是对话框界面和处理过程,不同的是通信对象。好了,下面让我们思考下如何实现同与不同。要实现在不同的窗口自由切换,非模式对话框的效果自然是最理想。要实现不同的通信对象,只要绑定不同的SOCKET就行。下面是笔者根据开发和应用的经验,总结得三种方案,希望能对其他朋友有所帮助。

方案一:窗口数组

窗口数组比较好理解,你要3个对话框,正好我那有3个一样的对话框,只要拿过来绑上不同的通信对象就行了。窗口数组流程就是启动的时候建好对话框数组,需要的时候显示窗口并绑定一个通信对象,不需要的时候隐藏窗口并移除通信对象。

首先主窗口类中添加对话框数组CTestDlg1 m_TestDlg[10],在主对话框的OnInitDialog()中创建对话框数组,注意这里创建的是非模式对话框。

for (int i=0;i<10;i++)

{

       m_TestDlg[i].Create(IDD_DIALOG2, GetDesktopWindow());

       m_TestDlg[i].m_bUseing = FALSE;

       m_TestDlg[i].ShowWindow(SW_HIDE);

}

上面要注意到需要有个标识变量来表示对话框是否在使用中。另外由于是非模式对话框,所以我们需要在对话框的DestroyWindow()中销毁它们,不然会造成资源泄露。

for (int i=0;i<10;i++)

{

       m_TestDlg[i].DestroyWindow();

}    

下面看看如何利用这些对话框,主要是对话框的显示和隐藏。在显示的时候绑定通信对象,在关闭对话框的时候隐藏窗口和移除通信对象

//查找一个没有在使用的对话框

for (int i=0;i<10;i++)

{

       if(m_TestDlg[i].m_bUseing == FALSE)

       {

              m_TestDlg[i].ShowWindow(SW_SHOW);

              m_TestDlg[i].m_bUseing = TRUE;

        //绑定通信对象代码略

              break;

       }

}

//重载m_TestDlg对话框的OnCancel()函数,同时设置使用标识为未使用

void CTestDlg1::OnCancel()

{

       // TODO: Add extra cleanup here

       AfxMessageBox("这里只是隐藏,而没有销毁对话框");

       ShowWindow(SW_HIDE);

       m_bUseing = FALSE;

    //移除通信对象

       //CDialog::OnCancel();

}

总体来说这个方案比较容易理解,过程也比较清晰,也是我最初想出来的方案。

方案二:多线程加消息循环

    很多人问为什么不直接创建非模式对话框?为了更好处理连接,我们使用了多线程。工作线程中缺乏对消息的响应机制,在其中创建模式对话框会造成窗口阻塞,创建非模式对话框会立即消失。方案二其实是构造一个UI线程,在线程里创建非模式对话框。因为该方案是多线程所以支持无限创建窗口,另外线程自带消息循环可以不同窗口前切换而不消息阻塞,并且在没有收到WM_QUIT消息前不会退出。

//具体线程实现,具体需要转换pParam并绑定通信对象

UINT WorkerThread(LPVOID   pParam)  

{

       CAboutDlg dlg;

       dlg.Create(IDD_ABOUTBOX);

       dlg.ShowWindow(SW_SHOW);

       MSG   msg;  

    while(GetMessage(&msg,NULL,0,0))  

    {  

              TranslateMessage(&msg);  

              DispatchMessage(&msg);  

       }  

       dlg.DestoyWindow();

       return 0;

}

要使用的时候,直接创建线程,传入通信对象就行了。值得注意的创建UI线程要使用AfxBeginThread而不是CreateThread

方案三:消息通知主窗口创建

主窗口是个UI线程,可以创建非模式对话框而且参与到主窗口的消息泵中不会销毁。方案三就是利用了这个特性,从而可以在工作线程中发送消息给主窗口并让其创建对话框。

添加自定义消息处理函数LRESULT OnDlgTest(WPARAM wParam, LPARAM lParam),响应消息WM_DLGTEST

//消息处理函数实现

LRESULT CTestModalDlg::OnDlgTest(WPARAM wParam, LPARAM lParam)

{

       CTestDlg* pDlg = new CTestDlg;

       pDlg->Create(IDD_DIALOG1, GetDesktopWindow());

       pDlg->ShowWindow(SW_SHOW);

       return 0;

}

当我们需要创建窗口的时候只要发送消息WM_DLGTEST给主窗口就行了。同前面的方案一样,需要非模式对话框都需要调用DestoryWindow来销毁窗口,另外方案三中要注意的是,pDlgnew分配的,需要delete指针,这个工作是重载CTestDlgPostNcDestroy函数,在其中释放自己。

三种方案中,笔者比较推荐方案三,支持窗口无限创建,代码量也相对较少,处理起来简单。笔者才疏学浅,如有错误之处,欢迎读者斧正。

你可能感兴趣的:(多线程,编程,工作,UI,dialog,任务)