你好,当前我写了一个功能处理的DLL,DLL调用者通过DLL提供的接口CreateWnd()创建并返回窗体指针。代码大概是:extern "C" __declspec( dllexport ) CWnd * CreateWnd( bool ( * OnShare )( void * pContext , CWnd * pShareWnd , char * buffer , int size ) , void * pContext, BOOL bServerFlag = FALSE )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
        //创建窗口
CMainFrame * frame = new CMainFrame( );//CMainFrame 派生于CFrameWnd
return frame;
}
接着,在DLL中创建的框架会启动一个线程,线程中会另外创建一个窗体。//DLL中的框架会启动线程
::AfxBeginThread(CMainFrame::ClientThread, this);
//DLL中的线程函数创建窗体
void RCClient::CreateDisplay() 
{
// Create the window
WNDCLASS wndclass;
wndclass.style = 0;
wndclass.lpfnWndProc         = WndProc;//窗体的消息处理函数
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = NULL;

wndclass.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_DOTCURSOR));
wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wndclass.lpszMenuName = (const TCHAR *) NULL;
wndclass.lpszClassName = VWR_WND_CLASS_NAME; RegisterClass(&wndclass); const DWORD winstyle = WS_VSCROLL | WS_HSCROLL | WS_CHILDWINDOW;

m_hwnd = CreateWindow(VWR_WND_CLASS_NAME,
      _T("远程桌面"),
      winstyle,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,       // x-size
      CW_USEDEFAULT,       // y-size
      m_hParentWin,          // Parent handle
      NULL,                // Menu handle
      NULL,
      NULL);
//SetParent(m_hwnd, m_hParentWin);
ShowWindow(m_hwnd, SW_HIDE);
// record which client created this window
SetWindowLong(m_hwnd, GWL_USERDATA, (LONG) this);
}
问题在于,DLL所创建的框架的更新事件无法影响到DLL线程中创建的那个窗体,就是当框架最小化或给某个窗体挡住或发生ON_SIZE等重绘窗体事件时,CreateWindow()出来的那个窗体里显示的内容无法正常显示。但是这并不是CreateWindow()那个窗体无处理ON_PAINT事件,因为如果把CreateWindow()的窗体属性指定为WS_OVERLAPPED即创建的窗体不附加在框架上而是处于最顶层窗体的时候,窗体能正常显示。DLL的框架无作ON_PAINT()消息的处理,因为我不知道要重绘什么,我的理解是所有绘制操作已经交给了CreateWindow()出来的那个窗体了。请问我要怎么解决这个问题呀?

解决方案 »

  1.   

    两窗体关系为:框架为父,线程内创建的那个为子,二个都有消息循环框架为MFC创建,理所当然是有的啦。,线程创建框架的子窗体,然后就进入消息循环。
    大概代码:
    DLL接口接收到事件,开启线程://在DLL中的框架
    LRESULT CMainFrame::OnStartThread(WPARAM wParam, LPARAM lParam)
    {
    static BOOL bOpened = FALSE;
    if( !m_bIsServer && !bOpened)
    {
    m_pRCClient = new RCClient(this, this->GetSafeHwnd());
    ::AfxBeginThread(CMainFrame::ClientThread, this); }
    return TRUE;
    }
    UINT CMainFrame::ClientThread(LPVOID pVoid)
    {
    CMainFrame *pMainFrame = (CMainFrame *)pVoid;
    try 
    {
    pMainFrame->m_pRCClient->Run();
    }
    catch (Exception &e)
    {
    e.Report();
    delete pMainFrame->m_pRCClient;
    } return TRUE;
    }//RCClient是一个继承于线程的类。
    void RCClient::Run()
    {
    CreateDisplay(); start_undetached();//RCClient内部的一个线程处理。        //这里就是线程内创建的窗体的消息循环了。
    MSG msg;
    try 
    {
    while ( GetMessage(&msg, NULL, 0,0) ) 
    {
    if (msg.message == WM_QUIT)
    {
    break;
    }
    else if (msg.message == WM_CLOSE)
    {
    break;
    }
    TranslateMessage(&msg); 
    DispatchMessage(&msg);

    } catch (WarningException &e)
    {
    e.Report();
    } catch (QuietException &e)
    {
    e.Report();
    }
    }
      

  2.   

    因为框架创建的子窗体要阻塞等待数据才能进行显示,如果不在线程中创建的话,子窗体会令整个程序处于锁定状态呀,我也是不得已才在线程中创建子窗体的。这个程序是为了实现VNC的功能,VNC的显示客户端(显示远程桌面的那一端)是一个独立的窗体,我把VNC的功能进行了些改造,使其脱离了网络及一些限制。并作为一DLL可以给其他应用程序调用而已
      

  3.   

    给父窗口加上WS_CLIPCHILDREN风格。
      

  4.   

    不是覆盖的问题,我试过在框架及子窗体中多加一层VIEW,也把VIEW设为子窗体的父了,但是也同样存在更新的问题,现在的现象是,只要不重绘框架,子窗体所显示的内容完全是可视正确的。我能否把代码发给你看看?我把重点的都注释一下,好吗?
      

  5.   

    用视图作为父窗口,同时给视图加上WS_CLIPCHILDREN风格,你先试试。我的邮箱:[email protected]
      

  6.   

    在 CMainFrame::ClientThread 的末尾加上:
            MSG msg;
    while(GetMessage(&msg, NULL, 0,0) ) 
    {
    TranslateMessage(&msg); 
    DispatchMessage(&msg);

    这些代码在
    ClientConnection::WndProc(....)
    {....
    case WM_DESTROY:
    ...
    PostQuitMessage(0);//找对位置,加这一行就搞定。
    return 0;
    ...
    }
      

  7.   

    在 CMainFrame::ClientThread 的末尾加上:
            MSG msg;
    while(GetMessage(&msg, NULL, 0,0) ) 
    {
    TranslateMessage(&msg); 
    DispatchMessage(&msg);

    这些代码在
    ClientConnection::WndProc(....)
    {....
    case WM_DESTROY:
    ...
    PostQuitMessage(0);//找对位置,加这一行就搞定。
    return 0;
    ...
    }
      

  8.   

    楼上的,消息循环我已经在run中实现了,就是说ClientThread的末尾不需要再加了。你是不是也弄过VNC呀?有没有把VNC的客户端那个窗体加到其他窗体中呀?
      

  9.   

    TO:cnzdgs
    我已经把求救信发到你的EMAIL了,你有空时,记得救救我,指导指导下喽!
      

  10.   

    。。不会吧,明天我弄个2005的给你。编译出错都是编译的强制性类型检查而已啊,我明天弄个2005的给你。你真的要帮帮我啊,这个项目太郁闷了。解决了我会共享代码上传到CSDN的资源去的,给有需要做远程桌面的同志点资源参考。我真的是指望你的啦大哥。