日期:2014-05-20  浏览次数:20833 次

求教 windows 窗口 显示原理。
看过许多windows消息循环的内容了。但还是感觉没有系统的掌握windows窗口显示的原理。

  句柄啊,GDI啊,windows消息循环啊,wndproc回调函数啊。

  窗体与控件的区别啊, 容器与控件的关系啊, 等等。

  尤其是当一个windows窗体程序,从运行到显示的过程中,几个关键点是什么,操作系统先创建了什么??再创建了什么,再根据什么执行的GDI中的代码从而在界面上绘制出了窗体,窗体容器与控件之间的关系 在代码中如何体现的。

  比如,我在c#中,一个控件在一个窗体上显示,代码一般是 new 一个控件。然后添加到form.controls集合中。在窗体的构造函数中执行此代码。

  但窗体类,控件类,执行的过程 与windows创建句柄,前后的关系是什么?
 
  写的比较乱,因为思维就比较乱。 望能尽可能系统的讲一下。前后的逻辑关系与对应关系。

   

 

------解决方案--------------------
大概说下我的理解吧:
句柄:句柄是窗口的标识,用来唯一的识别一个窗口
GDI:Win32下图形接口
windows消息循环:
先来看一下一个GUI程序的执行流程:
code=C/C++] while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}[[/code]
应用程序通过一个循环,不停的从消息队列里提取消息,并进行处理,可以看出,一个WinForm程序基本上是一个“死循环”,因为只要有消息,GetMessage就返回true。
这就是消息循环。
WndProc窗口过程:在上面的代码中,DispatchMessage函数用于将消息提交到窗口过程WndProc中,在这里你可以进行消息处理。
再来看看通常WndProc里的代码:
C/C++ code
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // 分析菜单选择:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: 在此添加任意绘图代码...
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

------解决方案--------------------
Petzold 之 Programming Windows Fifth Edition 那么厚的一本书.

不是 3 言 2 语就说清楚的.

简化的在线教程让我来给你推荐一下:
1.
theForger's Win32 API Tutorial
http://www.winprog.org/tutorial/
2.
Win32 Tips, Tricks and Tutorials
http://www.catch22.net/tuts
3.
Stromcode Win32/C++
http://www.stromcode.com/category/code/
4.
A programming tutorials on C++ language, C language, MFC Windows 
http://www.tenouk.com/

其他的 FunctionX, DevX, codeproject, codeguru 就不列了.

------解决方案--------------------
楼主啊……

前面的问题就不说了。

至于为什么不添加控件就不显示的问题,是因为,没有画上去。

控件,包括窗体,都有回调函数 OnPaint 方法,你一定没有接触过,这个是 WM_PAINT 消息的回调方法的外包装,你说得没错,消息循环是内部给处理好的了,先不说C#.net,便是MFC,你去创建一个UI线程,消息循环也是替你照顾好的。

UI的话,有一个结构,叫做“视觉树”,这是一个迭代过程,只有加入“树”中的元素才会递归地去显示到UI上。你新生成一个控件,但是你不将之加入到该“树”中,你当然看不到。因为,它被UI给忽略了,但它还是在内存中存在着。

我觉得你借着这个兴趣,应该去看看底层。.net也是一个体系,它也有底层。
------解决方案--------------------
我来终结这个帖子吧
就mfc窗口程序来说,
1. 给C***App填上虚拟函数 virtual BOOL PumpMessage();
填上代码:
BOOL CTestmfcApp::PumpMessage()
{
ASSERT_VALID(this);

if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
{
return FALSE;
}
if (m_msgCur.message==WM_ENDSESSION) {
AfxMessageBox("WM_ENDSESSION");
}

if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
{
::TranslateMessage(&m_msgCur);
theGroup++; // 这个为全局变量,只在这里被增加!

// 这个是输出函数,将消息利用OutputDebugString打印到 Dbgview.exe里面
// 格式自己定义,theMSGSTR 为一个类,里面封装了 消息字符串到消息值的映射
// 将消息的个数 theGroup 也打印出来