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

Directx3D9学习之二:Windows编程之最简单窗口程序

2015-01-31 23:05 676 查看

Directx3D9学习之二:Windows编程之最简单窗口程序

一、一些基本知识介绍
由于D3D的编程要借助于windows的窗口来体现,所以也需要懂一些windows的编程知识(以前做得比较多的是linux与android方面的程序,因此也要学习一下下啦)。
一些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,清除更新区域,表示绘图已经完成

三、最后的完整代码
#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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: