您的位置:首页 > 其它

【Chapter 2】基于Chp1的实例详解

2013-11-09 10:30 330 查看
写blog好累

一定要坚持下去啊TAT

代码是给我们培训的师兄的

里面的注释已经很详细了

特此鸣谢>3<

 

#include <windows.h>
#include <stdio.h>

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */

int CALLBACK WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int iCmdShow)

{
HWND hwnd;               /* This is the handle for our window */
MSG msg;            /* Here messages to the application are saved */
WNDCLASS wndclass;        /* Data structure for the windowclass */

static char szClassName[ ] = "WindowsApp";

/* 第一步:注册窗口类 */
wndclass.hInstance = hInstance;
wndclass.lpszClassName = szClassName;
wndclass.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;                 /* Catch double-clicks */
wndclass.cbWndExtra = 0;
wndclass.cbClsExtra = 0;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszMenuName = NULL;

/* Register the window class, and if it fails quit the program */
if (!RegisterClass (&wndclass))
return 0;

/* 第二步:创建窗口 */
hwnd = CreateWindow(
szClassName,
TEXT("MyApp"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,// initial x position
CW_USEDEFAULT,// initial y position
CW_USEDEFAULT,// initial x size
CW_USEDEFAULT,// initial y size
NULL,
NULL,
hInstance,
NULL
);

/* 第三步:显示窗口 */
ShowWindow (hwnd, iCmdShow);
UpdateWindow(hwnd);

/* 第四步:消息循环 */
while (GetMessage (&msg, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&msg);
/* Send message to WindowProcedure */
DispatchMessage(&msg);
}

/* The program return-value is 0 - The value that PostQuitMessage() gave */
return msg.wParam;
}

/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int mouseX, mouseY;
char s[100];
switch (message)
{
case WM_LBUTTONDOWN:
mouseX = LOWORD(lParam);
mouseY = HIWORD(lParam);
sprintf(s, "You clicked! x=%d, y=%d", mouseX, mouseY);
MessageBox(hwnd, s, "Message", 0);
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}


 

好了下面是自己对不理解的地方的注释

HWND hwnd;               /* This is the handle for our window */
MSG msg;            /* Here messages to the application are saved */
WNDCLASS wndclass;        /* Data structure for the windowclass */

static char szClassName[ ] = "WindowsApp";

/* 第一步:注册窗口类 */
wndclass.hInstance = hInstance;
wndclass.lpszClassName = szClassName;
wndclass.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;                 /* Catch double-clicks */
wndclass.cbWndExtra = 0;
wndclass.cbClsExtra = 0;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszMenuName = NULL;

/* Register the window class, and if it fails quit the program */
if (!RegisterClass (&wndclass))
return 0;


 

注册窗口类就把它当成一个类

wndclass就是这个类

下面跟着这个类的信息

hInstance是进程实例句柄,用来标识每个进程的(不是很理解 - -)

ipszClassName就是一个名字

wndclass.lpfnWndProc = WindowProcedure;  /* This function is called by windows */

style中的参数定义了窗口的特性,然后后面基于此类的窗口都继承这个特性。(有点疑惑)

cbClsExtra = 0; //窗口实例无扩展

cbClsExtra = 0; //窗口类无扩展

hIcon=LoadIcon(NULL,IDI_APPLICATION);// 窗口的最小化图标为缺省图标

hCursor=LoadCursor(NULL,IDC_ARROW); // 窗口采用箭头光标

hbrBackground=(HBRUSH)(GetStockObject(BLACK_BRUSH)); //窗口背景为黑色[BLACK]

wndclass.lpszMenuName=NULL; //窗口无菜单

 

if(!RegisterClass(&wndclass)) //如果注册失败

{return 0;}

 

/* 第二步:创建窗口 */
hwnd = CreateWindow(
szClassName,
TEXT("MyApp"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,// initial x position
CW_USEDEFAULT,// initial y position
CW_USEDEFAULT,// initial x size
CW_USEDEFAULT,// initial y size
NULL,
NULL,
hInstance,
NULL
);


CreateWindow(szClassName, TEXT("MyApp")中的szClassName要是上一步注册窗口中的ClassName

pszTitle, //窗口标题名

WS_OVERLAPPEDWINDOW, //窗口的风格

CW_USEDEFAULT,

CW_USEDEFAULT, //窗口左上角坐标值为缺省值

CW_USEDEFAULT,

CW_USEDEFAULT, //窗口的高和宽为缺省值

NULL, //此窗口无父窗口

NULL, //此窗口无子菜单

hInstance, //创建此窗口的应用程序的当前句柄

NULL //不使用该值

 

显示窗口和消息循环在这个程序中比较简单这里先不说

 

下面到过程窗口函数

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int mouseX, mouseY;
char s[100];
switch (message)
{
case WM_LBUTTONDOWN:
mouseX = LOWORD(lParam);
mouseY = HIWORD(lParam);
sprintf(s, "You clicked! x=%d, y=%d", mouseX, mouseY);
MessageBox(hwnd, s, "Message", 0);
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}


这里就用switch语句判断了message参数,对不同类型的消息进行不同的处理

case WM_DESTROY:

        PostQuitMessage (0);

        break;

default:

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

以上WM_DESTROY是安了关闭红叉叉

default是错误处理

 

而和别的程序不同的该程序的消息处理是

case WM_LBUTTONDOWN:

        mouseX = LOWORD(lParam);

        mouseY = HIWORD(lParam);

        sprintf(s, "You clicked! x=%d, y=%d", mouseX, mouseY);

        MessageBox(hwnd, s, "Message", 0);

        break;

即用一个MessageBox弹框显示鼠标单击位置的位置值

ps.wParam和IParam在附录1详细说明

 

附录1[离这么近附录个屁啊- -]

WPARAM 和 LPARAM,消息响应机制

wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数:

一个是WORD类型的16位整型变量;另一个是LONG类型的32位整型变量。因此根据匈牙利命名法,16位的变量就被命名为wParam, 32位的变量就被命名为lParam。

到了Win32API中,原来的16位变量也被扩展为32位,因此此时wParam和lParam的大小完全相同。

在Win32API的早期,为了保证和Win16API的代码可移植性MS定义了WPARAM和LPARAM两个宏。

当时保留了w前缀的原因一方面是由于WPARAM宏也已W开头,还有也因为要提醒程序员注意到可移植性,当然到了现在Win16早已退出历史舞台,这个前缀也就约定俗成的沿用下来了。

WPARAM 和 LPARAM 本质上没有什么区别:都是32位数,

但是区别也还是有的:除了上面几位若仁兄说的关于16位的的历史问题外,MICROSOFT在使用时两种参数分别代表不同的含义和内容,WPARAM常常代表一些控件的ID或者高位底位组合起来分别表示鼠标的位置,如果消息的发送者需要将某种结构的指针或者是某种类型的句柄时,习惯上用LPARAM来传递。

理论上在使用自定义消息时,WPARAM LPARAM的含义可以程序员任意指定的,但是最好遵从MFC中的习惯。在调用SendMessage()函数时,第二个参数是WPARAM,第三个参数是这个消息的LPARAM,但是你在程序中某个类中写下ON_MESSAGE()宏来处理这个消息时,处理函数SomeHandler(WPARAM,LPRAM(默认是0))中解释这两个参数时必须按照SendMessage调用中的意义来进行。

(以上看得有点云里雾里- -)

ps.什么是消息机制:

系统将会维护一个或多个消息队列,所有产生的消息都回被放入或是插入队列中。系统会在队列中取出每一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的程序的消息循环。每一个运行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口过程。而在没有消息时消息循环就将控制权交给系统所以Windows可以同时进行多个任务。

 

=====================================================

 

下一节要写到贪吃蛇了- -

当时觉得好难的说

人家一节课我都分了3 Chapter来写了TAT

好难过好伤感好脱力

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