您的位置:首页 > 编程语言

Windows编程之最简单窗口程序

2015-07-20 16:21 513 查看
一、一些基本知识介绍

一些windows编程的https://msdn.microsoft.com/en-us/library/ff381404(v=vs.85).aspx

Data typeSizeSigned?
BYTE8 bitsUnsigned
DWORD32 bitsUnsigned
INT3232 bitsSigned
INT6464 bitsSigned
LONG32 bitsSigned
LONGLONG64 bitsSigned
UINT3232 bitsUnsigned
UINT6464 bitsUnsigned
ULONG32 bitsUnsigned
ULONGLONG64 bitsUnsigned
WORD16 bitsUnsigned
WinDef.h中定义了BOOL值

#define FALSE    0
#define TRUE     1


p代表“指针”

lp代表“长指针

DWORD_PTR
INT_PTR
LONG_PTR
ULONG_PTR
UINT_PTR

头文件WinNT.h定义了如下typedef (基于UTF-16编码,即是16bit),为了支持Unicode

typedef wchar_t WCHAR;


一般来说,会经常看到如下编码的宽字符,即是前面加个L:

wchar_t a = L'a';
wchar_t *str = L"hello";

其他一些相关的typedef

TypedefDefinition
CHAR
char
PSTR or LPSTR
char*
PCSTR or LPCSTR
const char*
PWSTR or LPWSTR
wchar_t*
PCWSTR or LPCWSTR
const wchar_t*
windows支持unicode与ANSI,较新的则只支持Unicode
SetWindowTextA takes an ANSI string.
SetWindowTextW takes a Unicode string.

#ifdef UNICODE
#define SetWindowText  SetWindowTextW
#else
#define SetWindowText  SetWindowTextA
#endif

通过宏UNICODE来控制

MacroUnicodeANSI
TCHAR
wchar_t
char
TEXT("x")
L"x"
"x"
示范例子:

SetWindowTextW(L"My Application"); // Unicode function with wide-character string.

SetWindowTextA("My Application");  // ANSI function.

#ifdef _UNICODE
#define _tcslen     wcslen
#else
#define _tcslen     strlen
#endif


二、windows窗口编程

1、窗口句柄

HWND,通常来自以下两个函数的返回值

CreateWindow and CreateWindowEx.

要操作窗口通常需要使用HWND作为参数传入函数使用,例如移动窗口MoveWindow

BOOL MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint);

另外句柄不是指针,不存在
*hwnd
 

2、屏幕和窗口坐标

一般来说,windows的窗口都是以左上角为原点(0,0),另外一些坐标定义如图(图片来自msdn):



3、windows编程的入口点

WinMain or wWinMain

以wWinMain为例子

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);

hInstance:标识executable

hPrevInstance:现在已经没有使用,始终为0,以前用在16位的windows中。

pCmdLine:包含Unicode字符串的命令行参数

nCmdShow:一个flag,表示应用程序窗口的显示如:最大化,最小化或者正常。

4、创建一个窗口的过程

(1)注册一个窗口类

// Register the window class.
const wchar_t CLASS_NAME[]  = L"Sample Window Class";

WNDCLASS wc = { };

wc.lpfnWndProc   = WindowProc;
wc.hInstance     = hInstance;
wc.lpszClassName = CLASS_NAME;

lpfnWndProc:窗口过程,定义了绝多部分的动作

hInstance:来自wWinMain,实例句柄

lpszClassName:标识窗口类的字符串

传递WNDCLASS结构的地址给RegisterClass函数,注册窗口类到操作系统。

RegisterClass(&wc);

(2)创建窗口新实例

调用CreateWindowEx

HWND hwnd = CreateWindowEx(
0,                              // Optional window styles.
CLASS_NAME,                     // Window class

L"Learn to Program Windows",    // Window text
WS_OVERLAPPEDWINDOW,            // Window style

// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

NULL,       // Parent window
NULL,       // Menu
hInstance,  // Instance handle
NULL        // Additional application data
);

if (hwnd == NULL)
{
return 0;
}

第一个参数:
Optional window styles.


设定窗口中的一些可选行为(例如透明窗口),默认为0。

第二个参数:

Window class


定义窗口所创建的类型

第三个参数:

Window text

窗口标题,如果窗口存在标题栏则显示在其中。

第四个参数:

Window style

窗口的风格,定义了一些窗口外观和表现的标志组合,WS_OVERLAPPEDWINDO是几个标志结合的位或,包含最小化,最大化按钮,边框,标题栏等等

第五个参数:

Size and position


位置和大小 CW_USEDEFAULT 使用默认值

第六个参数:

Parent window


父窗口。

第七个参数:

Menu


菜单

第八个参数:

Instance handle


实例句柄

第九个参数:

Additional application data


指向void*的任意数据结构,传递数据所用

最后CreateWindowEx 返回句柄创建新窗口,如果失败返回0.

(3)显示窗口

要显示窗口则将窗口句柄传递给ShowWindow函数

ShowWindow(hwnd, nCmdShow);
 hwnd 参数来自CreateWindowEx 
nCmdShow参数用于最大化或者最小化窗口。操作系统将通过wWinMain函数传递该参数给程序

(4)窗口消息

窗口消息
MSG msg;GetMessage(&msg, NULL, 0, 0);
提取消息使用以下两个函数
TranslateMessage(&msg); DispatchMessage(&msg);

退出提取消息循环

退出提取消息循环

PostQuitMessage(0);

 WM_QUIT是一个特殊的消息,它会令消息循环结束。消息循环的示例:

// Correct.

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}


(4)窗口过程

The 
[b]DispatchMessage
 function
calls the window procedure of the window that is the target of the message. The window procedure has the following signature.[/b]

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

hwnd:窗口句柄
uMSg:消息代码
wParam、lParam:消息的其他数据

典型的窗口过程如下:

switch (uMsg)
{
case WM_SIZE: // Handle window resizing

// etc

}


一个典型的窗口过程可能需要处理几十条消息,因此它可能会变得非常长,这样可以将每个消息的逻辑处理封装到一个单独的函数中n,
然后再在switch中处理。

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
{
int width = LOWORD(lParam);  // Macro to get the low-order word.
int height = HIWORD(lParam); // Macro to get the high-order word.

// Respond to the message:
OnSize(hwnd, (UINT)wParam, width, height);
}
break;

}
}

void OnSize(HWND hwnd, UINT flag, int width, int height);
{
// Handle resizing
}

假如不处理窗口过程特定的消息,可以直接返回默认的DefWindowProc函数,

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


(4)绘制窗口内容

switch (uMsg)
{

case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);

// All painting occurs here, between BeginPaint and EndPaint.

FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));

EndPaint(hwnd, &ps);
}
return 0;

}

更新绘图有两种选择:
*只更新一部分
*更新全部区域

下面代码是更新整个区域,使用单一颜色,采用系统默认的COLOR_WINDOW,颜色取决于系统的配色方案
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));


完成绘图后,需要调用EndPaint,清除更新区域,表示绘图已经完成

三、最后的完整代码

[cpp] view
plaincopy





#ifndef UNICODE  

#define UNICODE  

#endif  

  

#include <Windows.h>  

  

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);  

  

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)  

{  

    //Register the window class  

    const wchar_t CLASS_NAME[] = L"Sample Window Class";  

    WNDCLASS wc = { };  

    wc.lpfnWndProc  = WindowProc;  

    wc.hInstance    = hInstance;  

    wc.lpszClassName    =   CLASS_NAME;  

  

    RegisterClass(&wc);  

  

    //Create the window.  

  

    HWND hwnd = CreateWindowEx(  

        0,              //Optional window styles.  

        CLASS_NAME,     //Window class  

        L"Learn to Program Windows",    //Window text  

        WS_OVERLAPPEDWINDOW,    //Window style  

  

        //Size and position  

        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,  

  

        NULL,               //Parent window  

        NULL,               //Menu  

        hInstance,          //Instance handle  

        NULL                //Additional application data  

        );  

  

    if(hwnd == NULL)  

    {  

        return 0;  

    }  

  

    ShowWindow(hwnd, nCmdShow);  

  

    //Run the message loop.  

  

    MSG msg = { };  

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

    {  

        TranslateMessage(&msg);  

        DispatchMessage(&msg);  

    }  

    return 0;  

}  

  

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  

{  

    switch (uMsg)  

    {  

    case WM_DESTROY:  

            PostQuitMessage(0);  

            return 0;  

        case WM_PAINT:  

            {  

                PAINTSTRUCT ps;  

                HDC hdc = BeginPaint(hwnd, &ps);  

                FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW+1));  

                EndPaint(hwnd, &ps);  

            }  

            return 0;  

    }  

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

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: