首页 > 学院 > 开发设计 > 正文

WINDOWS编程实验第一课

2019-11-06 08:13:54
字体:
来源:转载
供稿:网友

LRESULT CALLBACK WndPRoc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){    switch(msg)    {        case WM_CLOSE:            DestroyWindow(hwnd);        break;        case WM_DESTROY:            PostQuitMessage(0);        break;        default:            return DefWindowProc(hwnd, msg, wParam, lParam);    }    return 0;}首先这里是一个简单的窗口代码,在下面会进行详细的解释。
#include <windows.h>const char g_szClassName[] = "myWindowClass"; // Step 4: the Window ProcedureLRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow){WNDCLASSEX wc;HWND hwnd;MSG Msg;//Step 1: Registering the Window Classwc.cbSize = sizeof(WNDCLASSEX);wc.style = 0;wc.lpfnWndProc = WndProc;wc.cbClsExtra = 0;wc.cbWndExtra = 0;wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_application);wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);wc.lpszMenuName = NULL;wc.lpszClassName = g_szClassName;wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);if(!RegisterClassEx(&wc)){MessageBox(NULL, "Window Registration Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;}// Step 2: Creating the Windowhwnd = CreateWindowEx(WS_EX_CLIENTEDGE,g_szClassName,"The title of my window",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,NULL, NULL, hInstance, NULL);if(hwnd == NULL){MessageBox(NULL, "Window Creation Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;}ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd);// Step 3: The Message Loopwhile(GetMessage(&Msg, NULL, 0, 0) > 0){TranslateMessage(&Msg);DispatchMessage(&Msg);}return Msg.wParam;}

第一步是注册窗口类

  一个 窗口类 存储关于一个窗口的消息,包括控制窗口的窗口过程,窗口的大小图标,以及背景顏色.用这种方式,你可以先注冊一个窗口类,然后从它创建任意数目的窗口,而不需要一次次的指定这些参数.如果需要,大多数属性能针对单个的窗口来攺变.  这里说的窗口类与C++中的类是完全不同的概念.

接下来对每一个使用到的结构体成员进行分析

wc.cbSize        = sizeof(WNDCLASSEX);    wc.style         = 0;    wc.lpfnWndProc   = WndProc;    wc.cbClsExtra    = 0;    wc.cbWndExtra    = 0;    wc.hInstance     = hInstance;    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);    wc.lpszMenuName  = NULL;    wc.lpszClassName = g_szClassName;    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);    if(!RegisterClassEx(&wc))    {        MessageBox(NULL, "Window Registration Failed!", "Error!",            MB_ICONEXCLAMATION | MB_OK);        return 0;    }

cbSize  结构体的大小.style  类的式样(CS_*),不要跟窗口式样(WS_*)混淆了.这个一般设置为0.lpfnWndProc  指向这个窗口类的窗口过程的指针.cbClsExtra  配置给这个类的额外內存.一般为0.cbWndExtra  配置给这个类的每个窗口的额外內存.一般为0.hInstance  应用程序实例的句柄.(从WinMain()第一个参数传递来.)hIcon  当用戶按下Alt+Tab组合时候显示的大图标(一般为32*32).hCursor  在我们的窗口上显示的光标.hbrBackground  设置我们窗口背景顏色的背景刷子.lpszMenuName  这个类的窗口所用的菜单资源的名字.lpszClassName  类的名字.hIconSm  在任务栏和窗口的左上角显示的小图标(一般为16*16).

第二步:创建窗口

 hwnd = CreateWindowEx(        WS_EX_CLIENTEDGE,        g_szClassName,        "The title of my window",        WS_OVERLAPPEDWINDOW,        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,        NULL, NULL, hInstance, NULL);

第一个参数(WS_EX_CLIENTEDGE)是扩展的窗口式样设置类的名字(g_szClassName),告诉系统我们要创建什么样的窗口.设置WS_OVERLAPPEDWINDOW是一个窗口式样参数..四个参数(CW_USEDEFAULT,CW_USEDEFAULT,320,240)是窗口的左上角的X,Y坐标和其宽度和高度.把X,Y坐标设为CW_USEDEFAULT来让系统自己选择在屏幕的哪个地方来放置窗口.记住屏幕的最左边的X坐标为0并向右加;屏幕的顶部的Y坐标为0并向底加.单位是像素,这是屏幕在特定的分辨率下能显示的最小单位.再接下来的四个(NULL,NULL,g_hInst,NULL)分別是父窗口的句柄,菜单句柄,应用程序实例句柄,和窗口创建数据的指针.

第三步:消息循环

 while(GetMessage(&Msg, NULL, 0, 0) > 0)    {        TranslateMessage(&Msg);        DispatchMessage(&Msg);    }    return Msg.wParam;

GetMessage()从你应用的消息队列中取一个消息.TranslateMessage()为键盘事件做一些额外的处理,如随著WM_KEYDOWN消息产生WM_CHAR消息.

第四步:窗口过程

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;}

接下来是小组讨论

(1)通过查阅资料、读代码和写代码去验证,研究C语言typedef语句和宏的用法,以及在写Win32 API程序过程中的用途。typedef语句用法:1.常规变量类型定义例如:typedef unsigned char uchar 描述:uchar等价于unsigned char类型定义 uchar c声明等于unsigned char c声明2.数组类型定义 例如: typedef int array[2]; 描述: array等价于 int [2]定义; array a声明等价于int a[2]声明扩展: typedef int array[M][N]; 描述: array等价于 int [M][N]定义; array a声明等价于int a[M][N]声明3.指针类型定义 例如: typedef int *pointer; 描述: pointer等价于 int *定义;pointer p声明等价于int *a声明例如: typedef int *pointer[M]; 描述: pointer等价于 int *[M]定义 pointer p声明等价于int *a[M]声明明4.函数地址说明 描述:C把函数名字当做函数的首地址来对待,我们可以使用最简单的方法得到函数地址 例如: 函数:int func(void); unsigned long funcAddr=(unsigned long)func, funcAddr的值是func函数的首地址5.函数声明 例如: typedef int func(void); func等价于 int (void)类型函数 描述1: func f声明等价于 int f(void)声明,用于文件的函数声明 描述2: func *pf声明等价于 int (*pf)(void)声明,用于函数指针的生命,见下一条6.函数指针 例如: typedef int (*func)(void) 描述: func等价于int (*)(void)类型 func pf等价于int (*pf)(void)声明,pf是一个函数指针变量识别typedef的方法:a).第一步。使用已知的类型定义替代typdef后面的名称,直到只剩下一个名字不识别为正确 b).第二步.未知名字为定义类型,类型为取出名称和typedef的所有部分, c).第三部.定义一个变量时,变量类型等价于把变量替代未知名字的位置所得到的类型

(2)typedef语句和宏的使用有哪些优缺点?

typedef 是定义 一个名字的别名,别名等价于原名。原名仍存在,仍起作用。#define 是宏,预编译命令,在正式编译前作 字符串 替代,替代完毕再编译。原来的字符串不再存在,不再起作用。

(3)如果使用C++语言,怎样用更好的语法替代宏?

宏替换是C/C++系列语言的技术特色,C/C++语言提供了强大的宏替换功能,源代码在进入编译器之前,要先经过一个称为“预处理器”的模块,这个模块将宏根据编译参数和实际编码进行展开,展开后的代码才正式进入编译器,进行词法分析、语法分析等等。宏不遵循C++中关于范围和类型的规则。这经常导致一些微妙的或不那么微妙的问题。因此,C++提供更适合其他的C++(译注:原文为the rest of C++,当指C++除了兼容C 以外的部分)的替代品,例如内联函数、模板与名字空间。

(4)如果使用java语言呢?

“宏变量”:final修饰符的一个重要用途就是定义“宏变量”。当定义final变量时就为该变量指定了初始值,而且该初始值可以在编译时就确定下来,那么这个final变量本质上就是一个“宏变量”,编译器会把程序所有用到该变量的地方直接替换成该变量的值。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表