第3章 窗口与消息_3.2面向对象的窗口类的封装

3.2.1 MFC单文档大致框架

(1)MFC类继承略图

(2) MFC单文档应用程序类层次结构图

CWinApp:应用程序类,每个应用程序有且只有一个继承于CWinApp的派生类对象

CWnd:是一个通用的窗口类,用于提供Windows中的所有通用特性、对话框和控件。

(3)应用程序执行过程图

3.2.2 应用程序QWinApp的设计

//QWinApp.h文件

#include "stdAfx.h"

class QWinApp

{

public:

     QWinApp();

     ~QWinApp();

public:

     virtual BOOL InitInstance(); //提供接口,由派生类去实现窗口注册、创建等。

     virtual BOOL ExitInstance(); //应用程序结束前的收尾工作,如销毁指针等。

     void Run();  //消息循环

public:

     LPVOID m_pMainWnd;

};

//QMyWinApp.h的设计

#pragma once

#include "QWinApp.h"

class QMyWinApp : public QWinApp

{

public:

    QMyWinApp();

    ~QMyWinApp();

public:

    virtual BOOL InitInstance();

    virtual BOOL ExitInstance();

};

extern QMyWinApp theApp;

//QMyWinApp.c

#include "QMyWinApp.h"
#include "QMainFrame.h"

QMyWinApp::QMyWinApp(){}

QMyWinApp::~QMyWinApp(){}

QMyWinApp theApp;  //全局变量,先于WinMain执行,并将应用程序指针保存在g_pWinApp中。
BOOL QMyWinApp::InitInstance()

{
     QMainFrame* pMainFrame = new QMainFrame();
     assert(pMainFrame);

     m_pMainWnd = pMainFrame;

     //创建窗口
     BOOL bRet = pMainFrame->CreateEx(0, _T("MyFirstClass"), _T("我的第一个窗口程序"), WS_OVERLAPPEDWINDOW,
                                      CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL);

     if (!bRet)
     {
         MessageBox(NULL, _T("创建窗口失败!"), _T("创建窗口"), 0);
         return FALSE;
     }

      pMainFrame->ShowWindow(SW_SHOW); //显示窗口
      pMainFrame->UpdateWindow();      //更新窗口
      return TRUE;
}

BOOL QMyWinApp::ExitInstance()

{
     delete m_pMainWnd;  //删除主框架窗口
     m_pMainWnd = NULL;
     return TRUE;
}

3.2.3 一般窗口类QWnd的设计

(1)回调函数:必须是全局函数,不能是类的普通成员函数。且回调函数仅仅指明了窗口的句柄(hWnd),不能得到窗口的指针。那如何封装回调函数呢?

①MFC的做法:通过hWnd到CWnd对象指针的Map映射机制,将句柄转为指针。

②我们的做法:A、创建窗口时将窗口对象的指针保存在窗口类所指定的额外数据空间中,可以通过SetWindowLong存入并在回调函数中用GetWindowLong取出来,然后转化为窗口对象的指针,即调用类的成员函数。B、原回调函数就变成一个傀儡,真正在消息处理过程被该我们定义的虚函数WindowProc给接管了。

SetWindowLong函数——将窗口对象this指针保存在窗口类所关联的额外空间

HWND hWnd = CreateWindowEx(cs.dwExStyle,cs.lpszClass,cs.lpszName,cs.style,cs.x,cs.y,cs.cx,cs.cy,cs.hwndParent,cs.hMenu,cs.hInstance,this);

    assert(hWnd);
    m_hWnd =hWnd;
    SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)this);

GetWindowLong函数及消息处理

LRESULT CALLBACK QWnd::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{
    QWnd* pWnd = (QWnd*)GetWindowLong(hwnd,GWL_USERDATA); //从窗口额外空间得到窗口this指针
    if (pWnd)
    {
        return pWnd->WindowProc(uMsg,wParam,lParam);      //消息被路由到WindowProc处理。
    } 

    return ::DefWindowProc(hwnd, uMsg, wParam, lParam);

}

③WNDCLASSEX(或WNDCLASS)中的cbWndExtra成员用于指明紧跟窗口类之后额外创建的空间大小,以字节为单位。创建完之后,可以使用SetWindowLong函数来设置该额外空间的值,使用GetWindowLong来访问该空间的值。nIndex设定在0 ~ (额外空间大小- sizeof(long))之间。
    GWL_USERDATA标识符:当窗口类创建完成后,会自动创建一块32位数值的空间,可供用户自己处理,该空间与由cbWndExtra创建的额外空间无关,不能用GWL_USERDATA来设置或访问由cbWndExtra创建的额外空间。

(2)WM_Create和WM_NCCreate消息

  HWND hWnd =CreateWindowEx(cs.dwExStyle,cs.lpszClass,cs.lpszName,cs.style,cs.x,cs.y,cs.cx,cs.cy,cs.hwndParent,cs.hMenu,cs.hInstance,this);

  //说明:执行上面函数会发送WM_CREATE和WM_NCCREATE消息,由于执行这两条消息
  //期间CreateWindowsEx尚未返回,即得不到hWnd,也就无法在消息处理过程中利用
  //GetWindowLong和hWnd值取得this指针,所以必须手动在CreateWindowEx通用
  //lpParam参数传入this指针。然后在消息处理过程中,对这两个消息进行特殊处理。
    QWnd* pWnd = NULL;
     //处理CreateWindowEx过程中发送的两个消息中无法获取窗口对象指针的问题。
     if (uMsg == WM_CREATE || uMsg == WM_NCCREATE)
     {
         CREATESTRUCT *pCs = (CREATESTRUCT*)lParam;
         if (pCs)
         {              pWnd = (QWnd*)pCs->lpCreateParams; //窗口对象指针保存在lpCreateParams中

              if (pWnd)
              {
                   pWnd->m_hWnd = hWnd;
                   return pWnd->WindowProc(uMsg, wParam, lParam);
              }
         }
     }

3.2.4 让QWnd支持标准控件

(1)标准控件的窗口回调函数是操作系统注册的,并提供给用户。因回调函数不是我们指定的。消息便不能路由到我们所提供的WndProc中进行处理。

(2)标准控件的子类化——创建窗口后,采用子类化的机制用我们回调函数替换原先系统提供的窗口回调函数。

     //创建窗口

     HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style,
                               cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu ,cs.hInstance, this); //将this指针传给窗口过程
     assert(hWnd);

     m_hWnd = hWnd; 

     //将this指针保存在窗口类关联的额外空间中,在窗口过程中,可以GetWindowLong取回。

     ::SetWindowLong(hWnd, GWL_USERDATA, (LONG)this);

     //标准控件窗口过程路由到WndProc
     m_lpfnOldWndProc = (WNDPROC)::GetWindowLong(hWnd, GWL_WNDPROC);

     if (m_lpfnOldWndProc != WndProc)
     {
         //子类化控件——用我们的回调函数代替操作系统提供的回调函数。
         ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WndProc);   

         //模拟发送WM_CREATE和WM_NCCREATE消息
         //对于标准控件,因在CreateWindow时,窗体过程仍然是操作系统提供的,我们的WndProc会漏过这两个消息,所以模拟发送一下。
         WindowProc(WM_CREATE, 0, 0);
         WindowProc(WM_NCCREATE, 0, 0);
     }

3.2.5 资源创建控件的子类化处理

(1)资源创建的控件——即控件是从资源中生成的,并没有调用我们封装的CreateEx函数,所以消息不能路由到我们提供的WndProc中,这里需要提供一个函数来处理这个问题。

BOOL QWnd::SubClassWindows(HWND hWnd)
{
    if (m_hWnd == hWnd) return TRUE;

    m_lpfnOldWndProc = (WNDPROC)GetWindowLong(hWnd,GWL_WNDPROC);
    if(m_lpfnOldWndProc!=QWnd::WndProc)
    {
        m_hWnd =hWnd;
        SetWindowLong(m_hWnd,GWL_USERDATA,(LONG)this);
        SetWindowLong(m_hWnd,GWL_WNDPROC,(LONG)QWnd::WndProc);
        return TRUE;
    }
    return FALSE;
}

【附完整源码】

/***************************main.c*****************************************************/

#include "QWinApp.h"
#include "Global.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    QWinApp*  pWinApp = glbGetApp();
    assert(pWinApp);
    pWinApp->m_hInstance = hInstance;
    pWinApp->InitInstance();
    pWinApp->Run();
    pWinApp->ExitInstance();
    return TRUE;
}
/****************************Global.h文件*******************************************/

#pragma once
#include "stdAfx.h"
#include "QWinApp.h"
extern QWinApp* g_pWinApp;
extern QWinApp* glbGetApp();// global Get App;
 /****************************stdAfx.h文件*******************************************/

#pragma once
#include <Windows.h>
#include <tchar.h>
#include <assert.h>
 /****************************QWinApp.h文件*******************************************/

#pragma once
#include "stdAfx.h"
class QWinApp
{
public:
    QWinApp();
    ~QWinApp();
public:
    virtual BOOL InitInstance();
    virtual BOOL ExitInstance();
    void Run();
public:
    LPVOID m_pMainWnd;
    HINSTANCE m_hInstance;
};
 /****************************QWinApp.c文件*******************************************/

#include "QWinApp.h"
#include "Global.h"
QWinApp::QWinApp()
{
    m_pMainWnd = NULL;
    g_pWinApp = this;  //将theApp指针保存在全局变量中g_pWinApp。
}
QWinApp::~QWinApp()
{

}
BOOL QWinApp::InitInstance()  //接口,留给派生类去实现窗口注册、创建、显示等工作。
{
    return TRUE;
}
BOOL QWinApp::ExitInstance()   //应用程序结束前的收尾工作,如销毁指针等。
{
    return TRUE;
}
void QWinApp::Run()    //消息循环
{
    MSG msg;
    while (GetMessage(&msg,NULL,NULL,NULL))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
/****************************QMyWinApp.h文件*******************************************/

#pragma once
#include "QWinApp.h"
class QMyWinApp : public QWinApp
{
public:
    QMyWinApp();
    ~QMyWinApp();
public:
    virtual BOOL InitInstance();
    virtual BOOL ExitInstance();
};
extern QMyWinApp theApp;
 /****************************QMyWinApp.c文件*******************************************/ 

#include "QMyWinApp.h"
#include "QMainFrame.h"
QMyWinApp::QMyWinApp()
{
}
QMyWinApp::~QMyWinApp()
{
}
QMyWinApp theApp;
BOOL QMyWinApp::InitInstance()
{
    QMainFrame* pMainFrame = new QMainFrame();
    assert(pMainFrame);
    m_pMainWnd = pMainFrame;
    BOOL bRet = pMainFrame->CreateEx(0, _T("MyFirstClass"), _T("我的第一个窗口程序"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL);
    if (!bRet)
    {
        MessageBox(NULL, _T("创建窗口失败!"), _T("创建窗口"), 0);
        return FALSE;
    }

    pMainFrame->ShowWindow(SW_SHOW);
    pMainFrame->UpdateWindow();
    return TRUE;
}
BOOL QMyWinApp::ExitInstance()
{
    delete m_pMainWnd;
    m_pMainWnd = NULL;
    return TRUE;
}
/****************************QWnd.h文件*******************************************/ 

#pragma once
#include "stdAfx.h"
class QWnd
{
public:
    QWnd();
    ~QWnd();
public:
    HWND m_hWnd;
    WNDPROC m_lpfnOldWndProc;
public:
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs); //注册窗口类
    BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle,
                  int x, int y, int nWidth, int nHeight,
                  HWND hwndParent, HMENU nIDorHMenu, LPVOID lpParam = NULL);
    BOOL ShowWindow(int nCmdShow);
    void UpdateWindow();
    BOOL DestroyWindow();
public:
    static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
    virtual LRESULT Default(UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
    virtual LRESULT OnCreate(WPARAM wParam, LPARAM lParam);
    virtual LRESULT OnClose(WPARAM wParam, LPARAM lParam);
    virtual LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    virtual LRESULT OnPaint(WPARAM wParam, LPARAM lParam);
public:
    BOOL SubClassWindow(HWND hWnd);
    static QWnd* FromHandle(HWND hWnd);
};
/****************************QWnd.c文件*******************************************/
 #include "QWnd.h"
QWnd::QWnd()
{
    m_hWnd = NULL;
    m_lpfnOldWndProc = NULL;
}
QWnd::~QWnd()
{
}
BOOL QWnd::PreCreateWindow(CREATESTRUCT& cs)
{
    WNDCLASSEX wc = {0};
    //判断窗口类是否存在(比如标准控件(如按钮类),是由Window己经注册的,直接填充cs返回)
    //如果是标准控件,其窗口过程也是Windows而不是我们提供的。
    BOOL bRet = GetClassInfoEx(cs.hInstance,cs.lpszClass,&wc);
    if (bRet)
    {
        return TRUE;
    }
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.cbSize = sizeof(wc);
    wc.hbrBackground = (HBRUSH)GetStockObject(COLOR_HIGHLIGHTTEXT);
    wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
    wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
    wc.hIconSm = NULL;
    wc.hInstance = cs.hInstance;
    wc.lpfnWndProc = WndProc;  //如果是标准控件,这里的代码将执行不到。窗口过程己经由操作系统提供了。
    wc.lpszClassName = cs.lpszClass;
    wc.lpszMenuName = NULL;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    return  ::RegisterClassEx(&wc);
}
BOOL QWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle,
                    int x, int y, int nWidth, int nHeight, HWND hwndParent, HMENU nIDorHMenu, LPVOID lpParam)
{
    //注册窗口
    CREATESTRUCT cs;
    cs.cx = nWidth;
    cs.cy = nHeight;
    cs.dwExStyle = dwExStyle;
    cs.hInstance = (HINSTANCE)::GetModuleHandle(NULL);
    cs.hMenu = nIDorHMenu;
    cs.hwndParent = hwndParent;
    cs.lpCreateParams = lpParam;
    cs.lpszClass = lpszClassName;
    cs.lpszName = lpszWindowName;
    cs.style = dwStyle;
    cs.x = x;
    cs.y = y;
    BOOL bRet = PreCreateWindow(cs);
    if (!bRet)
    {
        return FALSE;
    }
    //创建窗口
    HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style,
                               cs.x, cs.y, cs.cx, cs.cy,
                               cs.hwndParent, cs.hMenu, cs.hInstance, this); //将this指针传给窗口过程
    assert(hWnd);
    m_hWnd = hWnd;
    ::SetWindowLong(hWnd, GWL_USERDATA, (LONG)this); //将this指针保存在窗口类关联的额外空间中,在窗口过程中,可以GetWindowLong取回。

    //标准控件窗口过程路由到WndProc
    m_lpfnOldWndProc = (WNDPROC)::GetWindowLong(hWnd, GWL_WNDPROC);
    if (m_lpfnOldWndProc != WndProc)
    {
        //子类化控件
        ::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WndProc);

        //模拟发送WM_CREATE和WM_NCCREATE消息
        WindowProc(WM_CREATE, 0, 0);   //对于标准控件,因在CreateWindow时,窗体过程仍然是操作系统
        WindowProc(WM_NCCREATE, 0, 0); //提供的,我们的WndProc会漏过这两个消息,所以模拟发送一下。
    }
    return TRUE;
}
//供Windows调用的回调函数——全局函数或静态成员函数,但不能是普通的类成员函数
LRESULT CALLBACK QWnd::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    QWnd* pWnd = NULL;
    //处理CreateWindowEx过程中发送的两个消息中无法获取窗口对象指针的问题。
    if (uMsg == WM_CREATE || uMsg == WM_NCCREATE)
    {
        CREATESTRUCT *pCs = (CREATESTRUCT*)lParam;
        if (pCs)
        {
            pWnd = (QWnd*)pCs->lpCreateParams; //窗口对象指针保存在lpCreateParams中
            if (pWnd)
            {
                pWnd->m_hWnd = hWnd;   //保存hWnd,因为WindowProc里面的函数可能用到m_hWnd
                //对于标准控件,m_lpfnOldWndProc记录的是操作系统提供的窗口过程
                pWnd->m_lpfnOldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
                return pWnd->WindowProc(uMsg, wParam, lParam);
            }
        }
    }
    pWnd = (QWnd*)::GetWindowLong(hWnd, GWL_USERDATA); //获取窗口对象的指针
    if (pWnd)
    {
        return pWnd->WindowProc(uMsg, wParam, lParam);    //消息路由到窗体的WindowProc中
    }

    return ::DefWindowProc(hWnd,uMsg,wParam,lParam);       //非窗体对象,则按缺省处理
}
BOOL  QWnd::ShowWindow(int nCmdShow)
{
    assert(m_hWnd);
    return ::ShowWindow(m_hWnd, nCmdShow);
}
void  QWnd::UpdateWindow()
{
    assert(m_hWnd);
    ::UpdateWindow(m_hWnd);
}
BOOL  QWnd::DestroyWindow()
{
    assert(m_hWnd);
    return ::DestroyWindow(m_hWnd);
}
LRESULT QWnd::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
        return OnCreate(wParam, lParam);  //虚函数OnCreate
        break;
    case WM_PAINT:
        return OnPaint(wParam, lParam);
        break;
    case WM_CLOSE:
        return OnClose(wParam, lParam);   //虚函数OnClose
        break;
    case WM_DESTROY:
        return OnDestroy(wParam, lParam); //虚函数OnDestroy
        break;
    }
    return Default(uMsg, wParam, lParam);
}
LRESULT QWnd::Default(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    //标准化控件的默认处理,由操作系统提供的窗体过程处理
    if (m_lpfnOldWndProc != QWnd::WndProc)
    {
        return m_lpfnOldWndProc(m_hWnd, uMsg, wParam, lParam);
    }
    return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam);

}
LRESULT QWnd::OnCreate(WPARAM wParam, LPARAM lParam)
{
    return Default(WM_CREATE, wParam, lParam);
}
LRESULT QWnd::OnClose(WPARAM wParam, LPARAM lParam)
{
    return Default(WM_CLOSE, wParam, lParam);
}
LRESULT QWnd::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    return Default(WM_DESTROY, wParam, lParam);
}
LRESULT  QWnd::OnPaint(WPARAM wParam, LPARAM lParam)
{
    return Default(WM_PAINT, wParam, lParam);
}
QWnd* QWnd::FromHandle(HWND hWnd)
{
    assert(hWnd);
    return (QWnd*)GetWindowLong(hWnd, GWL_USERDATA);
}
BOOL QWnd::SubClassWindow(HWND hWnd)
{
    assert(hWnd);
    //传进来的窗口与m_hWnd相同时,说明己经子类化过。
    if (m_hWnd == hWnd) return TRUE;
    m_lpfnOldWndProc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC); //提取传进来窗口的窗口过程
    if (m_lpfnOldWndProc != QWnd::WndProc)
    {
        //子类化
        m_hWnd = hWnd;
        SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
        SetWindowLong(m_hWnd, GWL_WNDPROC,(LONG)QWnd::WndProc);
        return TRUE;
    }
    return FALSE;
}
 /****************************QFrameWnd.h文件*******************************************/ 

#pragma once
#include "QWnd.h"
#include "QButton.h"
class QMainFrame :
    public QWnd
{
public:
    QMainFrame();
    ~QMainFrame();
public:
    LRESULT OnClose(WPARAM wParam, LPARAM lParam);
    LRESULT OnDestroy(WPARAM wParam, LPARAM lParam);
    LRESULT OnCreate(WPARAM wParam, LPARAM lParam);
public:
    QButton m_wndButton;
};
 /****************************QFrameWnd.c文件*******************************************/
#include "QMainFrame.h"
#define IDC_BUTTON 100001
QMainFrame::QMainFrame()
{
}
QMainFrame::~QMainFrame()
{
}
//msg
LRESULT QMainFrame::OnCreate(WPARAM wParam, LPARAM lParam)
{
    if (NULL == m_wndButton.m_hWnd)
    {
        m_wndButton.CreateEx(_T("按我呀!"),WS_CHILD|WS_VISIBLE|DFCS_BUTTONPUSH,0,0,200,120,m_hWnd,(HMENU)IDC_BUTTON);
    }
    return TRUE;
}
LRESULT QMainFrame::OnClose(WPARAM wParam, LPARAM lParam)
{
    if (IDYES == MessageBox(NULL, _T("确认要关闭窗口吗?"), _T("信息提示!"), MB_YESNO))
    {
        return DestroyWindow();
    }
    return TRUE;
}
LRESULT QMainFrame::OnDestroy(WPARAM wParam, LPARAM lParam)
{
    ::PostQuitMessage(0);
    return TRUE;
}
/****************************QButton.h文件*******************************************/
#pragma once
#include "QWnd.h"
class QButton :public QWnd
{
public:
    QButton();
    ~QButton();
public:
    virtual BOOL CreateEx(LPCTSTR lpszWindowName, DWORD dwStyle,
        int x, int y, int nWidth, int nHeight,
        HWND hwndParent, HMENU nIDorHMenu);
};
 /****************************QButton.c文件*******************************************/ 

#include "QButton.h"
QButton::QButton()
{
}
QButton::~QButton()
{
}
BOOL QButton::CreateEx(LPCTSTR lpszWindowName, DWORD dwStyle,
    int x, int y, int nWidth, int nHeight,
    HWND hwndParent, HMENU nIDorHMenu)
{
    return QWnd::CreateEx(0, _T("BUTTON"), lpszWindowName, dwStyle, x, y, nWidth, nHeight,
        hwndParent, nIDorHMenu, NULL);
}
时间: 2024-10-11 21:25:32

第3章 窗口与消息_3.2面向对象的窗口类的封装的相关文章

窗口和消息

窗口和消息 壹佰软件开发小组  整理编译   在前两章,程序使用了同一个函数MessageBox来向使用者输出文字.MessageBox函数会建立一个「窗口」.在Windows中,「窗口」一词有确切的含义.一个窗口就是屏幕上的一个矩形区域,它接收使用者的输入并以文字或图形的格式显示输出内容. MessageBox函数建立一个窗口,但这只是一个功能有限的特殊窗口.消息窗口有一个带关闭按钮的标题列.一个选项图标.一行或多行文字,以及最多四个按钮.当然,必须选择Windows提供给您的图标与按钮. M

2016年4月23学习经历总结(实现小功能窗口右下角消息弹窗框)

2016年4月23学习经历总结 作为一个前端初学者来说,初学的路上肯定会遇到很多问题,遇到问题的时候不要怕,相信自己,耐心.努力.坚持.方法.总结. 今天用javascript.HTML.CSS在做一个窗口右下角消息弹窗框遇到问题了, 遇到的问题:写完窗口右下角消息弹窗框代码后,功能没有实现,重要是在页面上的控制台还没有报错,而且在用严格模式下,js依然没有报错 作为一个菜鸟目前来说,我是用笨方法去排除, 怎么解决问题: 1.检查JS代码,语法,发现没有错,(如果有错的话控制台也会报错吧!) 2

《Windows程序设计 第5版》第3章 窗口与消息 笔记

广告先: LibUIDK界面库:制作QQ.360界面时,你能找到的最强大的界面库.基于DirectHWND技术! 3.1 窗口的创建 一个简单的win32程序如下(假设工程名为"HelloWin32",下面的代码是使用vc6.0创建一个名为HelloWin32的"Win32 Application",并且选择"A typical "Hello World" application"后创建的代码精简后得到): // HelloW

第27章 窗口与消息(1)

27.1 线程的消息队列 (1)Windows用户对象(User Object) ①类型:图标.光标.窗口类.菜单.加速键表等 ②当一个线程创建某个对象时,则该对象归这个线程的进程所有,当进程结束时,如果用户没有明确删除这个对象,则操作系统会自动删除这个对象. ③窗口和钩子(hook)这两种用户对象,它们分别由建立窗口和安装钩子的线程所拥有(注意,不是进程).如果一个线程建立一个窗口或安装一个钩子.然后线程结束,操作系统会自动删除窗口或卸载钩子. ④窗口及线程的拥有关系使得建立窗口的线程必须为它

第三章、窗口与消息

应用程序的每个窗口都有一个窗口过程函数与之关联,Windows通过调用窗口过程向窗口传递消息.窗口过程依据消息做相应处理,然后将控制权返还给Windows. 窗口类标识了用于处理传递给窗口的消息的窗口过程,允许多个窗口共享同一窗口类. 消息队列中存放着应用程序可能创建的所有窗口的消息,消息循环从消息队列中检索消息,并将其分发给相应的窗口过程. #include <Windows.h> #include <mmsystem.h> #pragma comment(lib, "

《Windows程序设计》读书笔三 窗口与消息

第三章 窗口于消息 前面的例子都使用MessageBox来创建窗口 ,单他所创建的窗口灵活性有限. 3.1 窗口的创建 只要调用CreateWindow函数即可 3.1.1 系统结构概述 一个应用程序窗口可能包含,标题栏,菜单栏,工具栏,滚动条.另外还有一种类型的窗口是对话框,这种窗口可以不带标题栏 还可能包含,按钮,单选按钮,复选框,列表框,滚动条,文本框等.每一个这些对象都被称为 子窗口,或者 控件窗口 当用户改变窗口尺寸时,Windows便向应用程序发送一条携带新窗口尺寸相关的信息,接着应

眼见为实(2):介绍Windows的窗口、消息、子类化和超类化

眼见为实(2):介绍Windows的窗口.消息.子类化和超类化 这篇文章本来只是想介绍一下子类化和超类化这两个比较"生僻"的名词.为了叙述的完整性而讨论了Windows的窗口和消息,也简要讨论了进程和线程.子类化(Subclassing)和超类化(Superclassing)是伴随Windows窗口机制而产生的两个复用代码的方法.不要把"子类化.超类化"与面向对象语言中的派生类.基类混淆起来."子类化.超类化"中的"类"是指W

2.窗口与消息

知识点: 1.窗口程序的创建 2.窗口的注册 3.系统窗口类的注册 4.应用程序全局窗口类的注册 5.窗口类的风格 6.窗口类的查找过程 7.相关API 8.窗口的创建 9.子窗口的创建 10.窗口类和窗口的附加数据 11.Windows消息机制 12.什么是消息? 13.窗口处理函数和消息 14.消息相关函数 15.Windows常用消息 16.消息的获取 17.消息的发送 18.消息的分类 19.消息队列 20.消息和消息队列 21.消息的获取 22.GetMessage/PeekMessa

C#代码像QQ的右下角消息框一样,无论现在用户的焦点在哪个窗口,消息框弹出后都不影响焦点的变化,那么有两种方法

你QQ的右下角消息框一样,无论现在用户的焦点在哪个窗口,消息框弹出后都不影响焦点的变化,那么有两种方法: 要么重写需要弹出的窗体的事件: protected override CreateParams CreateParams     {     get     {         const int WS_EX_NOACTIVATE = 0x08000000;         CreateParams cp = base.CreateParams;         cp.ExStyle |=