Win32 编程基础
Win32 API编程入门
欢迎阅读theForger's Win32 API教程第二版(简体中文)作者:Brooks Miles译者:湛宗儒 本教程试图使用尽可能快和尽可能清晰的方法教你开始Win32 API开发.它是以一个整体来组织的,所以在你提问之前请从头到尾看一遍...你的大多数问题很可能在文字中已被回答.每个章节以之前的章节为基础.我也在附錄A中附上了一些常见的错误的解決方法.如果你问一些在教程中已被回答的问题的话,看起来就有点不聪明了.·下载完整的范例源代码,在整个教程都有对代码的引用.·或是下载整个教程( 包括源代码)至你自己的计算机上慢慢看.下到硬盘的版本可能不包括网络版本具有的一些如拼写更正之类的小规模修改. 如果你在一个別的站点上看此教程,请访问#winprog 站点看最新的官方版本. · ·目錄·基础1.开始 学习2.一个简单的窗口3.处理消息4.理解消息循环5.使用资源6.菜单和图标7.对话框 , 图形界面设计者的好朋友8.非模态 对话框9.标準控件: 按钮 , 编辑框 , 列表框 , 靜态 控件10.等等 , 我还想问 ...( 对话框常见问题)·创建一个简单应用1.应用第一部分 : 在运行时创建控件2.应用第二部分 : 使用文件与常用对话框3.应用第三部分 : 工具栏与状态栏4.应用第四部分 : 多文档界面·图形设备界面1.位图 , 设备上下文与BitBlt2.透明位图3.定时器与动画4.文本 , 字体与顏色·工具与文档1.推荐的书与参考2.免费的Visual C++ 命令行工具3.免费的Borland C++ 命令行工具·附表附表A:常见错误的解決方法附表B:为什要在学习MFC 编程之前学习API附表C:关于资源文件 我听某些读者说教材中的源代码在一些很旧的Netscape浏览器中不能正确地換行,如果你遇到此问题请参考zip打包下载的源代码.想做点什么?你可以绝对免费地使用此文档,但是把在它放在互联网上的确是有些费用..如果你感觉它对你有帮助,也想回馈一些,我将很感谢你能捐赠任何数目的款项来协助支撐此网站.此页面每月大約有15,000个点击,并且在一直增加:) 再说一次,你完全沒有义务支付,你也不会因为支付而得到除了在此处之外的任何东西,但是你想协助的话,是很好的...就点那个PayPal图片就行.但愿你能享受閱读,Brook 我想对如下几个人做出的贡献表示感谢:Yih Horng,Todd Troxell,T FrankZvovushe,Suzanne Lorrin, Seth McCarus,Crispina Chong,John Crutchfield,Scott Johnstone,Patrick Sears,Juan Demerutis,Richard Anthony,Alex Fox,Bob Rudis,Eric Wadsworth,Chris Blume.还有那些写信告诉我觉得此文档有用的那些读者.我很高兴!需要进一步的帮助? 一般地话我会免费回复求助邮件,或指出在哪里可以找到可供参考的资源. 现在我正忙于几个大项目,所沒有时间跟你写一些特定的范例或一定规模的软件项目.但是我愿意接项目:)尽管联系我 .Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.开始学习这篇教程讲什么 这篇教程试图向你展现使用Win32 API写程序的一些基础知识(还有常见的扩展知识).使用C语言,大多数的C++工具也可以编译.事实上从大多数语言的介绍文章可知,大多数语言皆可调用API,包括Java,汇编语言以及Visual Basic.但是我将不会提到这些语言的代码例子,你想使用其它语言的话,请自己参考相关资料,不过有好几个使用过此教程的人都对我说用上面的这些语言都是可行的. 本教程不会教你C语言,也不会教你怎么使用你喜欢的编译器(Borland C++,Visual C ++,LCC-Win32,等等).但是我将在附表中就我对编译器的所知提供一些说明. 如果你不知道macro或typedef是什么,或switch()语句如何工作,那你要先回去找一本好的C语言的教程学习一下.重要说明 在此文档的某些部分我将指出某些地方很重要.因为很多人在不閱读它们情況下造成理解困难,你如果不閱读,你很可能也陷入困难. 第一个就是: 以zip打包的源代码范例不是可选可不选的!我沒有把所有的代码放在教程中,只放了那些与我正在讨论问题相关的.要想知道这里的代码怎么与其它部分配合,就必须去看zip文件中的源代码. 好!第二个: 把整个文档看完.如果你在读某章节遇到了问题,请耐心一点,很可能在后面一点就可以找到答案.如果你实在不能忍受这种无知的状态,请在到IRC频道上去提问或发出求助邮件之前至少跳过一点或在余下的文档中搜一下(是的,计算机可以搜索). 另外一点就是一个关于话题A的问题很可能在关于话题B或C的讨论中得到解答,也有可能是话题L.所以多看看,找一下. 好,东扯西拉暂时告一段落,我们来试些实际代码.最简单的Win32程序 如果你是一个完全的新手,就让我们来确认一下你可以编译一个基本的windows程序.把下面这些代码弄到你的编译器中去编译一下,如果一切正常你就得到有史以来最简易的程序之一. 记得以C来编译,不是以C++.可能沒有关系,但这里的代码都是C,在正确的轨道,行驶还是好些.大多数情況,你要做的就是把文件的扩展名写成.c而不是.cpp..如果这些话伤了你的脑筋的话,就把文件名写成test.c并用它就行了.#include <windows.h>int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow){MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK);return 0;} 如果不行,首先閱读得到的任何错误提示,并在帮助文档或任何其它跟你编译器配套的文档中查找它们.确定你是以一个Win32 GUI(不是Console)的工程/makefile/目标来编译的.不幸的是,这一点上我也帮不了什么,对于不同的编译器(不同的人),解決方法不同. 你可能得到一些警告说你沒有使用WinMain()传递的那些参数.这沒关系.现在我们确定你能编译一个程序了,我们来看一下代码...int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow) WinMain()是Windows中与DOS或UNIX的main()的等价物.这是你的程开始执行的入口.参数如下:HINSTANCE hInstance程序可执行模块的句柄(內存中的.exe文件).HINSTANCE hPrevInstance在Win32程序中总是为NULL.LPSTR lpCmdLine命令行参数组成的一个单字符串.不包括程序名字.int nCmdShow一个将要传递给ShowWindow()的整数,我们在后面进行讨论. hInstance用作装入资源或其它的以模块为单位的任务.一个模块是一个装入到你程序的exe或dll.对于本教程的大多数部分(如果不是全部的话),我们只关心一种模块,就是exe 模块. hPrevInstance在Win16时代曾经用作你程序的前面已经运行的实例(如果有的话).现在已经不用了,在Win32中你忽略它就行了.调用规则 WINAPI指定调用规则并被定义为_stdcall.要是你不知道它是干什么用的,先不管它,在我们的这个教程中它对我们沒有影响.记住在这个位置我们需要它就是了.Win32数据类型 你会发现很多普通的关键字或类型在windows中有特定的定义.UINT是unsigned int,LPSTR是char*等等...你怎么用完全取決于你自己.你要是喜欢char*超过了LPSTR,那就用就是了.当然在你替換一个数据类型前你要确定你知道它是什么. 就记住一些容易记住的东西就夠了.LP前缀代表Long Pointer.在Win32中,Long这个部分已经是过时的概念,不要管它.要是不知道指针是什么的话,你可以1)去找一本好的C语言教程,或2)直接往下读,弄得头脑混乱.我是推荐第一种方案的,但很多人使用第二种(我也是:).到时候別说我沒有提醒你. 接下来,一个C接在LP后面表示是常量指针.LPCSTR表示一个指向不会也不能被修改的常量字符串的指针.LPSTR指向的就不是常量的,可以被修改. 你可能还会看到一个T混在里面.现在不要管它,除非你打算与Unicode打交道,它沒有其它的意义.Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.一个简单的窗口范例:simple_window 有时候有人在IRC上问:”我怎么才实现一个窗口?”...我觉得不是一句两句能说得清楚.虽然一旦你搞清楚你要做什么后并不难,但是你的确需要做一些事情来使显示一个窗口;这些事情不是在聊天室中一下子说得清楚的.我总是喜欢先做一件事情然后来理解它...所以先给出一个简单窗口的代码稍后再做解释.#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;} 简单来说这是你想创建一个窗口能写的最简单的程序,大致上70行左右的代码.如果第一个范例你通过了编译,这个也应该不成问题.第一步:注冊窗口类 一个窗口类存储关于一个窗口的消息,包括控制窗口的窗口过程,窗口的大小图标,以及背景顏色.用这种方式,你可以先注冊一个窗口类,然后从它创建任意数目的窗口,而不需要一次次的指定这些参数.如果需要,大多数属性能针对单个的窗口来攺变. 这里说的窗口类与C++中的类是完全不同的概念.const char g_szClassName[] = "myWindowClass"; 上面的变量存储了我们窗口类的名字,马上会用来向系统注冊窗口类. WNDCLASSEX wc;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;} 这是我们在WinMain()中注冊我们的窗口类的代码.我们填写一个WNDCLASSEX结构体的成员并调用RegisterClassEx(). 结构体的成员对窗口类的影响如下:cbSize 结构体的大小.style 类的式样(CS_*),不要跟窗口式样(WS_*)混淆了.这个一般设置为0.lpfnWndProc 指向这个窗口类的窗口过程的指针.cbClsExtra 配置给这个类的额外內存.一般为0.cbWndExtra 配置给这个类的每个窗口的额外內存.一般为0.hInstance 应用程序实例的句柄.(从WinMain()第一个参数传递来.)hIcon 当用戶按下Alt+Tab组合时候显示的大图标(一般为32*32).hCursor 在我们的窗口上显示的光标.hbrBackground 设置我们窗口背景顏色的背景刷子.lpszMenuName 这个类的窗口所用的菜单资源的名字.lpszClassName 类的名字.hIconSm 在任务栏和窗口的左上角显示的小图标(一般为16*16). 如果看得不很明白先不要担心,马上会有讲解.另外要记住的一件事情是不要试图去记下这些东西.我基本上不(从来不)记结构体或函数的参数,这样做是浪费精力和更重要的时间.如果你知道要调用的函数你就去花几秒钟在你的帮助文档中查一下.要是沒有帮助文档,就是想法弄到.沒有它们是很郁闷的.随著你使用多次后也许你会记住那些最常用的函数的参数. 然后我们调用RegisterClassEx()并检查是否成功,如果失败我们弹出一条提示消息并从WinMain()函数退出程序.第二步:创建窗口 一旦类注冊完,我们即可从它创建一个窗口.你应该去查一下CreateWindowEx()的参数列表(在你要用一个新API的时候你总是要这样做),但是我会在这里做个简单的介绍.HWND hwnd;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)是扩展的窗口式样,这里我设置它想得到一个內部下陷的边框效果.你可以设成0看看效果.要习惯于试不同的值看效果. 接下来我设置了类的名字(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)分別是父窗口的句柄,菜单句柄,应用程序实例句柄,和窗口创建数据的指针.在windows系统中,你屏幕上的窗口是以分层次的父窗口,子窗口的形式来组织的.当你看到一个窗口中有一个按钮时候,按钮就是子窗口,包含它的窗口就是父窗口.我们的例子中,父窗口的句柄为NULL,因为这里沒有父窗口,这个是是我们的主窗口或是顶层窗口.菜单也是NULL,因为我们现在也沒有菜单.实例句柄设为我们从WinMain()得到的第一个参数.窗口的创建数据(我们几乎沒有使用)可以用来向创建的窗口发送额外数据在这里也设为NULL. 如果你想知道神奇的NULL是什么,它实际上被定义为0(零).而且在C中,它是被定义为((void*)0)的,因为是用来作指针用的.所以你有可能在把NULL当整数使用时会得到警告,跟你的编译器的警告级別设置有关.你可以忽略这个警告,也可以用0来代替. 不检查调用是否成功几乎是程序员为找不来程序究竟错在哪里而烦恼的最常发生的情況.CreateWindow()可能会调用失败,即使你是一个用经验的程序员,原因就是可能犯错误的地方实在太多了.除非你学会了如何快速查出错误,最少你应该给自己一个机会知道是哪里出了错,一定记住检查返回值!if(hwnd == NULL){MessageBox(NULL, "Window Creation Failed!", "Error!",MB_ICONEXCLAMATION | MB_OK);return 0;} 在我们创建了窗口并作检查以确定我们有一个正确的句柄后,我们使用WinMain()最后的参数来显示窗口,再更新它以确认它在屏幕上正确地重画了自己.ShowWindow(hwnd, nCmdShow);UpdateWindow(hwnd); nCmdShow是可选的参数,你可以简单地传递SW_SHOWNORMAL即可.但是用从WinMain()传来的参数可给予运行此程序的用戶选择以可视,最大化,最小化等选项...来引导程序的自由.你可以在windows快捷方式的属性中看到这些选项,参数由选项来決定.第三步:消息循环 这是整个程序的心臟,程序中几乎所有的控制都从这个点传递. while(GetMessage(&Msg, NULL, 0, 0) > 0){TranslateMessage(&Msg);DispatchMessage(&Msg);}return Msg.wParam; GetMessage()从你应用的消息队列中取一个消息.任何时候用戶移动鼠标,敲击键盘,点击你窗口的菜单,或做別的什么事,系统会产生消息并输入到你的程序的消息队列中去.调用GetMessage()时你请求将下一个可用的消息从队列中删除并返回给你来处理.如果队列为空,GetMessage()阻塞.如果你不熟悉这个术语,它意味著一直等待直到得到一个消息,才返回给你. TranslateMessage()为键盘事件做一些额外的处理,如随著WM_KEYDOWN消息产生WM_CHAR消息.最后DispatchMessage()将消息送到消息应该被送到的窗口. 可能是我们的主窗口或另外一个,或一个控件,有些情況下是一个被系统或其它程序创建的窗口.这不是你需要担心的,因为我们主要关心我们得到消息并送出,系统来做后面的事以确认它到达正确的窗口.第四步:窗口过程 如果说消息循环是程序的心臟,那个窗口过程就是程序的大脑.这里所有送到窗口的消息被处理.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;} 窗口过程在每个消息到来时被调用一次,HWND参数是消息相应的窗口的句柄.这很重要因为你可能用相同的类创建了两个或多个窗口并且它们用相同的窗口过程(WndProc()).不同点就在不同的窗口有不同的hwnd参数.比如我们得到WM_CLOSE消息我们就要销毀那个窗口.我们使用了窗口句柄作为我们得到的第一个参数,其它的窗口都不会受影响,除了那个我们想要操作的之外. WM_CLOSE是在我们按下关闭按钮或按下Alt+F4组合时产生的.这默认会使窗口销毀,但我喜欢显式处理它,因为这是在程序退出之前做清除检查,或询问用戶是否保存文件等事情的绝佳的位置. 当我们调用DestoryWindow()系统向要销毀的窗口送出WM_DESTORY消息,这里是我们的窗口,并在从系统移除我们的窗口之前删除它剩下的所有的子窗口.因为这是我们的程序中唯一的窗口,我们準备好了并希望程序退出,所以我们调用了PostQuitMessage().这样会向消息循环发出WM_QUIT消息.我们不永远收不到这个消息,因为它使GetMessage()返回FALSE,而且你也可以看到我们的消息循环代码中,这时候我们停止处理消息并返回最终的结果码,我们传递给PostQuitMessage()的WM_QUIT中的wParam部分.这个返回值只有在你的编程为被別的程序调用并且你需要一个确定的返回值时候才有真正有用.第五步:沒有第五步Phew(喘一口气),到这先告一段落.如果上面还沒有解释清楚的话,还是先放下,也许我们在讲解更有用的程序时这些东西会变得清晰起来.Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.处理消息范例:window_click 不错,我们有个窗口了,不过除了DefWindowProc()允许它做的,如拉抻,最大化等等之外沒有別的什的功能了,并不是很令人激动. 下一章节我将演示如何修改你已有的代码来加点新东西.现在我只来告诉你”处理这个消息,在这里处理...”你就知道我的意思,知道怎样做且不用看一整个例子.希望如此,所以注意看:P 对于初学者,请把我们最后那个窗口编译好并确信它能工作.然后你要么就在这个例子上修改要么拷到另外一个新工程中来修改. 我们準备加个使用戶点击我们的窗口时候能夠显示出我们程序的名称的功能.不是很酷,就是基本的一个消息的处理.让我们看看我们的WndProc()中有些什么: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;} 如果我们想处理鼠标的点击,我们需要添加一个WM_LBUTTONDOWN的处理部分(对于右键与中间键,分別是WM_RBUTTONDOWN与WM_MBUTTONDOWN). 如果你听到我或其它人提到处理消息,就是说在窗口的类的WndProc()中加上如下代码:LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_LBUTTONDOWN: // <-// <- 这就是我们加的break; // <-case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;} 不同消息处理的代码的顺序基本上沒有什么关系.要记住的是一定不要忘了在每个消息处理代码后写上break语句.你可以看到我们在我们的switch()中加了另外一个case.现在我们想要在我们的程序执行至此时发生点什么. 首先我们把我们要加的代码写出来(显示我们程序的文件名)然后整合到我们的程序中去.后面的章节中我将只写出代码让你自己整合到程序中去.对我来说不用打那么多字了,对你来说也更灵活,不只是这里的程序还可以加到任何程序中去.如果你不知道怎么办,请参考样例zip文档中对应此章的部分.GetModuleFileName(hInstance, szFileName, MAX_PATH);MessageBox(hwnd, szFileName, "This program is:", MB_OK | MB_ICONINFORMATION); 这段代码不是自解释的,你不能把它随便敲到你原来的代码中去.我们只想在用戶用鼠标点击的时候运行这段代码,所以我们把它加到我们的消息处理框架中去:LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_LBUTTONDOWN:// BEGIN NEW CODE{char szFileName[MAX_PATH];HINSTANCE hInstance = GetModuleHandle(NULL);GetModuleFileName(hInstance, szFileName, MAX_PATH);MessageBox(hwnd, szFileName, "This program is:", MB_OK |MB_ICONINFORMATION);}// END NEW CODEbreak;case WM_CLOSE:DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;} 注意那对新的花括号{}.当你在switch()中定义变量时需要它.这本来是基础的C语言知识,但我认为我应该在此指出来,为那些理解有困难的读者著想. 如果你已经加进了代码,现在就编译它.如果正常的话,你点击窗口你就应该看到一个有.exe字样的对话框弹出来. 你可能已经注意到我们加了两个变量,hInstance与szFileName.查一下GetModuleFileName()你就会看到第一个参数是HINSTANCE.指向可执行文件(我们的程序,.exe文件).我们哪里得到这样一个东西?GetModuleHandle()给出了答案.GetModuleHandle()的说明指出传给它一个NULL会返回一个创建发出调用进程的文件句柄,正是我们刚刚提到的HINSTANCE,是我们需要的.把这些消息集中起来我们就会得到如下的定义:HINSTANCE hInstance = GetModuleHandle(NULL); 对于第二个参数,我们再次转向我们可以信赖的参考文档,我们看到它是”一个用来接收那个模块的文件名和路径的缓冲区的指针”而且数据类型是LPTSTR(要是你的文档是比较旧的话就是LPSTR).因为LPSTR等价于char*,我们就定义一个字符串:char szFileName[MAX_PATH]; MAX_PATH是在<windows.h>中定义的一个宏,用来定义Win32中文件名缓冲区的最大长度.我们也将MAX_PATH传给GetModuleFileName()以使它知道缓冲区的大小. GetModuleFileName()被调用后,szFileName将包括一个我们的.exe文件名的字符串,以null结尾.我们把它传递给MessageBox()以一个简单的方法向用戶显示. 所以如果你加了代码,编译了.如果正常,点击窗口你就会看到一个有.exe文件名的对话框弹出来. 如果不是这样,这里是完整的代码.跟你的比较一下,看错误在哪里.#include <windows.h>const char g_szClassName[] = "myWindowClass";LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch(msg){case WM_LBUTTONDOWN:{char szFileName[MAX_PATH];HINSTANCE hInstance = GetModuleHandle(NULL);GetModuleFileName(hInstance, szFileName, MAX_PATH);MessageBox(hwnd, szFileName, "This program is:", MB_OK |MB_ICONINFORMATION);}break;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;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;}hwnd = 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);while(GetMessage(&Msg, NULL, 0, 0) > 0){TranslateMessage(&Msg);DispatchMessage(&Msg);}return Msg.wParam;}Copyright © 1998-2003, Brook Miles (theForger). All rights reserved.理解消息循环 在写任何有实际价值的程序之前,都要理解整个消息循环和windows程序传递消息的结构.当前为止我们已经试了一些消息的处理,我还应该更进一步的看一下这个过程, 因为你如果不理解它们的话,后面的內容将会对你很难.什么是消息 一个消息就是一个整数.如果你到头文件中看一下(了解API的好地方)你就会发现这样的內容:#define WM_INITDIALOG 0x0110#define WM_COMMAND 0x0111#define WM_LBUTTONDOWN 0x0201...等等..消息用来进行windows系统中的所有通信,至少在基本方面是这样的.如果你想要你的窗口或是控件(其实就一种特別的窗口)做点什么你就给它发个消息. 如果另外一个窗口要你做点什么它也发给你一个消息..如果发生了用戶按动了键盘,移动了鼠标,点击了一个按钮之类的事件,系统就向相关的窗口发送消息.你要是就是那个被传至消息的窗口,你就要处理这些消息. 每个windows消息可能拥有至多两个参数,wParam和lParam.最初wParam是16bit,lParam是32bit,但在Win32平台下两者都是32bit.不是每个消息使用了这些参数,而且每个消息以不同的方式来使用.比如,WM_CLOSE不使用它们任一个,所以你应该忽略它们.WM_COMMAND消息两个都使用,wParam有两个部分,HIWORD(wParam)中含有提示消息(如果有的话),LOWORD(wParam)含有发送消息的控件或菜单的标识号.lParam含有发送消息的控件的HWND(窗口的句柄)或者为NULL,当消息不是由控件发送. HIWORD()和LOWORD()是windows定义的两个宏,用来从一个32bit值中分离出高字(0xffff0000)和低字(0x0000ffff)的两字节.在Win32中,一个WORD是16bit,所以一个DWORD为32bit. 可以用PostMessage()或SendMessage()来发送消息.PostMessage()把消息放入消息队列再立即返回.就是说你调用了PostMessage()后消息可能被处理了,也可能还沒有被处理. SendMessage()则真接把消息送往窗口并且在窗口沒有结束处理消息之前不返回.如果我们想关闭一个窗口我们可以发送一个WM_CLOSE消息:PostMessage(hwnd,WM_CLOSE,0,0);这跟我们点击窗口顶部的按钮一样的效果.注意wParam和lParam都为0.这是因为我们刚才说了WM_CLOSE并不用它们.对话框 一旦你开始使用对话框,你将需要向此控件发送消息以与它们通信.你可以先使用GetDlgItem()来用ID得到控件的句柄然后用SendMessage(),也可以直接用SendDlgItemMessage()这个一步到位的函数.你给它一个窗口的句柄和一个子窗口的ID,它就会得到字窗口的句柄并向它发送消息.SendDlgItemMessage()和类似的API,如。
pywin32简易入门(转)
pywin32简易⼊门(转)停更⼀年多了,最近对PY产⽣了兴趣,应为想解放双⼿,⼜不想⽤按键精灵之类的软件,于是乎就百度到了这个东东“pywin32”打开了新世界的⼤门,So,就在这记录学习笔记吧。
⾔归正传准备部分1pip install pywin32准备部分2⼯欲善其事必先利其器,先装个Spy++,百度⼀⼤把,就不放链接了,具体使⽤⽅法参考这⾥(⼀段简短的介绍)不过也够⽤了。
代码部分⾸先import win32guiimport win32conwin = win32gui.FindWindow('Notepad','新建⽂本⽂档.txt - 记事本')tid = win32gui.FindWindowEx(win,None,'Edit',None)win32gui.SendMessage(tid, win32con.WM_SETTEXT, None, '你好hello word!')win32gui.PostMessage(tid,win32con.WM_KEYDOWN,win32con.VK_RETURN,0)print("%x" % tid)print("%x" % win2)⼀句⼀句解释:win = win32gui.FindWindow('Notepad','新建⽂本⽂档.txt - 记事本')这⾥搬运⼀下⼤佬博客的解释,FindWindow(lpClassName=None, lpWindowName=None)描述:⾃顶层窗⼝(也就是桌⾯)开始搜索条件匹配的窗体,并返回这个窗体的句柄。
不搜索⼦窗⼝、不区分⼤⼩写。
找不到就返回0 参数:lpClassName:字符型,是窗体的类名,这个可以在Spy++⾥找到。
lpWindowName:字符型,是窗⼝名,也就是标题栏上你能看见的那个标题。
轻松走进Win32汇编语言
“
一
P o D g i R T : i 皿 , D O I :W R) :W R) r c i  ̄ n P O O DI l o :W R) D O I D O I , ,
MⅡ L
语句放在数据段中,是一个 函数的定义,这个和 C 语言也无太 多区别 ,如果子程序 的定义语句在引用的后面 ,开发者就必
维普资讯
必需 l蹦 6 1 以上版本才能够汇编 Wn 2 i砒锄 6 1 只要 / ̄ i .1
一
L
Ⅱ 1 ou eae Old lX n
个 虬. X E E文 件就 可 以 了 T r o  ̄ M . ( A M)是 u b Kt j O T S S
须先进行定义,当然,这个定义是针对  ̄ v k 语句和其 noe 他带参数的调用的,如果开发者的子程序没有参数 ,开发者 就可以用 c ] 指令去调用它而不是用宏指令  ̄v k ,此 al no e 时 ,开发 者就 不必声 明此 函数 了。 接下来 的代码段包含 了子程序与主程序,在 p o r c后的
“ L DG
_
序上,汇编语言有其不可 取代的优越性。相信通过本文的阅读, 言的大致印象 好戏在后面, 本期专题 拭 目以待,别看花 了眼哦。
M I e u 语句 ,相 当于 C语言的  ̄ e i e A N q 1 d fn
D G L
_
M I 1 A N ,用来预 定义一些常量。
es le
… ex FL E a AS
rt e
ed f n i mv ex T E 。 a 刚
rt e
P0 Dg 1 c l h
s ̄ " t 2 t:
d p
“
ue s sr 语句表示其后的寄存器要编译器 自动插入保存及恢复
Win32教程33-RichEdit控件_基础知识
你会注意到版本2和3都使用了相同的DLL文件名,而且它们也使用了相同的类名!这样在你想要明确的使用RichEdit 3.0的功能的时候就会产生问题. 到目前为止,我还找到一个正式的方法来区分版本2.0和3.0.不过,有个解决方法工作良好,我会在后面演示给你看.
CFM_STRIKEOUTdwEffects 成员中的 CFE_STRIKEOUT 值是有效的.
CFM_UNDERLINEdwEffects 成员中的 CFE_UNDERLINE 值是有效的.
dwEffects字符效果. 可以是以下值的组合
CFE_AUTOCOLOR使用系统正文颜色
CFE_BOLD粗体字符
dwMask位标记, 用来指定下面的那些成员是有效的.
CFM_BOLDdwEffects 成语中的 CFE_BOLD 值是有效的.
CFM_CHARSETbCharSet 成员是有效的。
CFM_COLORcrTextColor 成员跟 dwEffects中的 CFE_AUTOCOLOR 值是有效的.
CFE_ITALIC斜体字符
CFE_STRIKEOUT字符带删除线
CFE_UNDERLINE字符带下划线
CFE_PROTECTED字符是受保护的; 企图改变字体会产生一个EN_PROTECTED 通知消息.
yHeight字符高度, 单位是 twips ( 1/1440 英寸 或者 1/20 的打印机的打印点).
lParam == 指定要设置的颜色的 COLORREF 结构,仅当 wParam 为 0 时才有效.
譬如, 如果我要设置背景为纯蓝色,我需要写入以下代码:
invoke SendMessage,hwndRichEdit,EM_SETBKGNDCOLOR,0,0FF0000h
LCC-win32
LCC-Win32小指南By Daniel Guerrero Miralles翻译:pigprince声明本文没有任何明确的或者含蓄的表达说明本文是完全正确的,对于应用本文内容所产生的任何结果,本人概不负责。
请原谅本文在语言和语法的的运用上的错误,本人才疏学浅,这是不可避免的。
如果有什么你觉得不舒服的地方请联系pigprince,先谢谢了_________________________________________________________________LCC-Win32介绍LCC-Win32原来是一个免费的开放源代码WIN32编译器,包含一个很好用的IDE,用起来很爽,但是最近源码开始要付费的了(40美圆)。
详情请见LCC-Win32官方网站。
它的免费版本可以在国内得到,到云风工作室看一下,你会有所收获。
目录* 简介* 编译器的安装* Lcc-Win32的一些基本概念* 写个小程序!* 使用工程管理* 第一个Windows程序* 程序生成向导* 使用WeditRes创建资源* 添加其它类型的资源* 使用非规格资源* 静态库和动态库简介其实所谓的简介这个部分的内容趋向取决于作者。
但是我所读过的一些指南都是由一个“简介”开始的,这部分的内容通常都是在重复读者会在下面看到的东西,但是也有的简介只是作者的一些想法。
仔细的想一下,其实这个介绍并不是一件简单的事情。
首先,如果你要是开门见山的直奔主题,这是不礼貌的,而且基于web的指南也不应该有超大个的简介,不应该让读者在这个东西上浪费时间和金钱。
看来我的废话也够多的了,让我们切入正题。
这个指南是单页的,建议你等浏览器下载完毕后保存一份拷贝来离线阅读。
编译器的安装编译器的安装简单极了,只要把您下载的文件运行一下就OK了,应该不会遇到什么问题。
但是注意安装的最后要编译库文件,可能要花点时间,要视你的机器速度而定。
Lcc-Win32的一些基本概念Lcc-Win32编译系统是由多个文件构成的。
第02课 - Win32编程基础知识
C语言入口函数
Windows程序设计-基础教程
例如 dir /w /p c:\windows argc = 4 argv[0] = dir argv[1] = /w argv[2] = /p argv[3] = c:\windows
17
代码规范-函数头的注释模板
Windows程序设计-基础教程
每行字符不要超出80个字符(“/”加上“-” 的总长度是80个字符; “FUNC”为函数的名称; “IN”为输入的参数; “OUT”为在函数内部的输出信息内容,即函数 参数作为返回值的说明; “RETURN”函数的返回值(如:函数成功返 回TRUE,否则返回FALSE。); “AUTHOR”为作者信息,需要时间的写法; “NOTE”为函数功能的描述,其中包括:功 能描述、全局变量描述以及调用模块。
Windows 数据类型
C 数据类型
char * const char *
Windows 类型
LPSTR, PSTR LPCSTR, PCSTR
void
void *
VOID
LPVOID
22
Windows 新增数据类型:句柄类型 * *
Windows程序设计-基础教程
HINSTANCE HWND HANDLE HPEN HBRUSH HBITMAP HFONT HDC HRESOURCE HCURSOR ……
8
代码规范-函数命名
Windows程序设计-基础教程
第一个字母必须使用大写字母,要求用大小写字 母组合规范函数命名,必要时可用下划线间隔, 示例如下: int GetValue(); void* Word_GetApp();
WIN32汇编程序PPT课件
例4
count darray
.model small .386
;采用32位指令
.stack
.data
equ 10
dd 20,4500h,3f40h,-1,7f000080h
dd 81000000h,0fffffff1h
dd -45000011,12345678
dd 87654321
.code
.startup
条件转移
转移范围可达到32位全偏移
Jcc label
;cc为真,转移到label指定的转段移内范偏围移仍地为址处短转移
JECXZ label ;ECX=0,转移到label指定的段内偏移地址处
LOOP/LOOPZ/LOOPNZ label ;循环指令,32位段采用ECX作为计数器
例1
;将AX的每一位依次重复一次 ;所得的32位结果保存于EAX中 mov ecx,16 mov bx,ax next:shr ax,1 rcr edx,1 shr bx,1 rcr edx,1 loop next mov eax,edx
;平衡堆栈
通用寄存器全部进出栈
PUSHA
;顺序将AX/CX/DX/BX/SP/BP/SI/DI压入堆栈
POPA
;顺序从堆栈弹出 DI/SI/BP/SP/BX/DX/CX/AX (与PUSHA相反) ;其中应进入SP的值被舍弃,并不进入SP,SP 通过增加16来恢复
符号扩展和零位扩展
MOVSX r16,r8/m8 ;把r8/m8符号扩展并传送至r16 MOVSX r32,r8/m8/r16/m16 ;把r8/m8/r16/m16符号扩展并传送至r32 MOVZX r16,r8/m8
三、32位指令的程序设计
win32汇编除法
win32汇编除法1. 简介win32汇编是一种低级编程语言,用于在Windows操作系统上编写应用程序。
在win32汇编中,除法操作是非常常见的,它允许将两个数相除并得到商和余数。
本文将介绍win32汇编中的除法操作,包括如何使用除法指令、处理异常和处理特殊情况。
2. 除法指令win32汇编提供了两个除法指令:div和idiv。
•div指令用于无符号整数的除法操作。
它使用eax寄存器作为除数,并将商存储在eax中,余数存储在edx中。
•idiv指令用于有符号整数的除法操作。
它使用eax寄存器作为除数,并将商存储在eax中,余数存储在edx中。
以下是一个示例程序,展示如何在win32汇编中使用除法指令:mov eax, 10 ; 设置除数mov ebx, 3 ; 设置被除数div ebx ; 无符号整数除法; 此时 eax = 3(商),edx = 1(余数)idiv ebx ; 有符号整数除法; 此时 eax = -3(商),edx = 1(余数)3. 处理异常在进行除法操作时,可能会出现一些异常情况,例如被除数为0或除数与被除数的符号不同。
为了处理这些异常,win32汇编提供了一些标志位。
•CF(Carry Flag)标志位用于指示除法操作是否溢出。
如果除数为0,则CF会被设置为1。
•ZF(Zero Flag)标志位用于指示商是否为0。
如果商为0,则ZF会被设置为1。
以下是一个处理除法异常的示例程序:mov eax, 10 ; 设置除数mov ebx, 0 ; 设置被除数为0div ebx ; 无符号整数除法jnc success ; 如果没有溢出,跳转到成功处理的标签; 处理除法异常的代码; ...success:; 处理除法成功的代码; ...4. 处理特殊情况除法操作还涉及一些特殊情况的处理。
例如,当进行除法操作时,如果商的结果无法放入指定的寄存器,会导致溢出。
为了处理这种情况,可以使用cwd指令将32位有符号整数转换为64位有符号整数。
windows环境下32位汇编语言程序设计附书代码
windows环境下32位汇编语言程序设计附书代码汇编语言是一种底层计算机语言,用于编写与计算机硬件直接交互的程序。
在Windows环境下,可以使用32位汇编语言进行程序设计。
本文将介绍一些常见的32位汇编语言程序,并附带相关的代码示例。
1.程序的基本结构:在32位汇编语言中,程序的基本结构由三个部分组成:数据段、代码段和堆栈段。
数据段用来声明和初始化程序中使用的全局变量和常量。
例如,下面的代码段声明了一个全局变量message,存储了一个字符串。
```data segmentmessage db 'Hello, World!',0data ends```代码段包含了程序的实际执行代码。
下面的代码段使用`mov`指令将message变量中的字符串存储到寄存器eax中,并使用`int 21h`来调用MS-DOS功能1来显示字符串。
```code segmentstart:mov eax, offset messagemov ah, 09hint 21hmov ah, 4chint 21hcode ends```堆栈段用来存储函数调用过程中的局部变量和返回地址。
2.入栈和出栈操作:在程序中,我们经常需要使用堆栈来保存和恢复寄存器的值,以及传递函数参数和保存函数返回值。
以下是一些常用的堆栈操作指令: ```push reg ;将reg中的值压入堆栈pop reg ;将堆栈顶部的值弹出到reg中```下面的示例演示了如何使用堆栈来保存和恢复寄存器的值:```code segmentstart:push eax ;将eax保存到堆栈mov eax, 10 ;设置eax的值为10pop ebx ;将堆栈顶部的值弹出到ebxadd eax, ebx ;将eax和ebx相加int 3 ;调试中断,用于程序的暂停mov ah, 4chint 21hcode ends```3.条件判断和跳转指令:汇编语言中的条件判断和跳转指令用于根据条件的成立与否来改变程序的执行流程。
第9章 Win32编程
第9章
Win32编程
9.1.1 Windows API的有关概念
Windows API都是以DLL输出函数的形式提供的, 大部分核心的API服务都在Kernel32.dll、GUI32.dll和 User32.dll三个文件内,它们位于Windows\System (Winnt\System32)目录内。还有许多重要的API函数在 Windows (Winnt)或Windows\System (Winnt\System32) 目录中的其它DLL文件内(本章第5节将介绍DLL)。这 些函数数量庞大,而且随着Windows版本的升级仍在 不断增加。对于普通程序员来说,不可能也没必要知 道每个API函数的用法,但应了解一些API的知识并且 能在需要时迅速查到自己感兴趣的API函数的资料。
GetActiveWindow、FindWindow等API函数取得其句柄。
第9章
Win32编程
下面一个例子是在当前Windows环境下查找一个标 题为“Hello”的窗口,如果查到该窗口,就将其标题 改为“How Are You”。 HWND hWnd ; if (hWnd = FindWindow (0, "Hello"))
判断一个窗口是否处于最小化状态
改变窗口的位置 改变窗口的位置和大小
第9章
Win32编程
BringWindowToTop FindWindow FlashWindow GetWindowText
将指定的窗口带到顶部 寻找符合某些条件的窗口 使指定的窗口闪烁显示 取窗口的标题或控件的内容
SetWindowText
运行外部应用程序 退出Windows并关闭或重新启动系统等 创建形状各异的窗口 打开剪贴板 清除剪贴板上的数据 关闭剪贴板
Windows程序设计-第02章-Win32编程基础知识
在C语言的世界里,所有的程序都是用函数来装配的,main称之为主函数,是所有程序运行的入口。main函数可以无参,也可以有参,但标准的C语言,main函数是有参函数,其形式如下所示:
int main(int argc, char* argv[])
{
printf("Hello World!\n");
第2章
Windows编程,大家也通常称为win32编程,或win32 SDK编程,其含义是针对32位Windows操作系统。本章节回顾了C语言的入口函数,再引入Win32入口函数,通过win32开发所需要的相关知识,巩固对Win32编程的理解。
Win32编程具体的功能是什么?它是为Windows系统编写应用程序的工具或手段,目的是为了服务于系统用户。当然,Win32程序就是所有可以在Windows系统下运行的程序的统称。因为Windows是由很多窗口组成,所以这里所指的Windows程序,即为窗口程序。
char *
LPSTR, PSTR
const char *
LPCSTR, PCSTR
void
VOID
void *
LPVOID
Win32的数据类型众多,有上百个,记忆时可以使用一些技巧,切勿死记硬背,拿“LPCSTR、PCSTR”为例:
“LP”与“P”代表同一含义,即指针;
“C”代表“const”;
“STR”则代表字符串。
2.2
C语言有入口函数,当然Win32编程也有入口函数,虽然它们的写法有所不同,但同为入口函数,基本功能是一样的。不一样的是Win32的入口函数相对来说更为复杂,它为窗口应用程序提供相应的参数。为了让大家更好的了解Win32入口函数的参数,先来了解一下C语言的一些参数,表2.1描述了常用的数据类型。
Win32多线程编程
(2)CloseHandle,用于关闭对象,其函数原型为: BOOL CloseHandle(HANDLE hObject);
如果函数执行成功,则返回 TRUE;否则返回 FALSE,我们可以通过 GetLastError 函数进一步可以获 得错误原因。
C 运行时库 在 VC++6.0 中,有两种多线程编程方法:一是使用 C 运行时库及 WIN32 API 函数,另一种方法是使 用 MFC,MFC 对多线程开发有强大的支持。 标准 C 运行时库是 1970 年问世的,当时还没有多线程的概念。因此,C 运行时库早期的设计者们不可能考 虑到让其支持多线程应用程序。 Visual C++提供了两种版本的 C 运行时库,-个版本供单线程应用程序调用,另一个版本供多线程应用程序 调用。多线程运行时库与单线程运行时库有两个重大差别: (1)类似 errno 的全局变量,每个线程单独设置一个; 这样从每个线程中可以获取正确的错误信息。 (2)多线程库中的数据结构以同步机制加以保护。 这样可以避免访问时候的冲突。
通过下列代码就可以遍历系统中的进程,获得进程列表:
//获取当前进程总数 EnumProcesses(process_ids, sizeof(process_ids), &num_processes);
//遍历进程 for (int i = 0; i < num_processes; i++)
{ //根据进程 ID 获取句柄 process[i] = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0,
2、获取进程信息 在 WIN32 中,可使用在 PSAPI .DLL 中提供的 Process status Helper 函数帮助我们获取进程信息。 (1)EnumProcesses()函数可以获取进程的 ID,其原型为:
Windows平台Python编程必会模块之pywin32
Windows平台Python编程必会模块之pywin32在Windows平台上,从原来使⽤C/C++编写原⽣EXE程序,到使⽤Python编写⼀些常⽤脚本程序,成熟的模块的使⽤使得编程效率⼤⼤提⾼了。
不过,python模块虽多,也不可能满⾜开发者的所有需求。
⽽且,模块为了便于使⽤,通常都封装过度,有些功能⽆法灵活使⽤,必须直接调⽤Windows API来实现。
要完成这⼀⽬标,有两种办法,⼀种是使⽤C编写Python扩展模块,或者就是编写普通的DLL通过python的ctypes来调⽤,但是这样就部分牺牲掉了Python的快速开发、免编译特性。
还好,有⼀个模块pywin32可以解决这个问题,它直接包装了⼏乎所有的Windows API,可以⽅便地从Python直接调⽤,该模块另⼀⼤主要功能是通过Python进⾏COM编程。
安装时可以直接使⽤pip执⾏“pip install pywin32”来安装它。
安装完毕后,在Python安装路径下的Lib\site-packages\win32可以看到所有的API⽀撑模块,Lib\site-packages\win32com下则是COM的⽀撑模块。
在Lib\site-packages下有⼀个PyWin32.CHM帮助⽂件,相信对Windows编程有⼀定基础的,看了这个帮助⽂件就能很快上⼿。
简单说,pywin32把Windows API按照功能分了⼀些⼤类,每⼀个⼤类作为⼀个模块。
以下是所有的模块:mmapfile odbc perfmon servicemanager timer win2kras win32api win32clipboard win32consolewin32cred win32crypt win32event win32evtlog win32file win32gui win32help win32inet win32jobwin32lz win32net win32pdh win32pipe win32print win32process win32profile win32ras win32securitywin32service win32trace win32transaction win32ts win32wnet winxpgui⽐如⽂件类API就在模块win32file中,进程类API在模块win32process中。
Lcc-win32面向Windows编程图解教程
Lcc-win32面向Windows编程图解教程为什么使用Lcc?当各种版本Visual C++ Windows编程的书汗牛充栋的时候,当无论是高手还是初学者都用Visual C++ 编程的时候,干嘛要有用Lcc进行Windows编程的书?⏹ Lcc是自由软件,公开源代码,至少是免费的!虽然V isual C++的学生版或速成版很便宜,尤其是用美元计价且用高级程序员的收入衡量的时候。
但微软的商品即便免费给你,你的感觉仍是被拴住鼻子,早晚你会把血汗钱给盖茨,劫贫济富一把。
⏹ 用Lcc能深入了解编程是怎么回事。
Windows编程的工具太强大,他就会代替你做很多基础层面的事。
而这些基础正式初学者应该熟练掌握的!想想为什么我们小学时先学加减法而不是想学使用计算器。
但是如果工具太简单也不行,用小刀是无法刻出CPU的。
⏹ Lcc软件的作者们是一群编程的精英,包括Dennis Ritchie, C语言的发明者。
他们花费了惊人的脑力写出Lcc的IDE、编译器和丰富的文档,我们若不学会用它,不是太暴殄天物了吗?为什么使用C语言?C语言的历史很悠久,所以他的缺点被揭露、他被批判的历史也很长。
可是好多编程语言出现又消失,C语言的地位仍未被撼动。
而且C语言被更为广泛的应用。
正如Lcc所自带的文档《Programming with lcc-win32》所说的:如果你想写能被长时间使用的软件,不要学当今最火的编程语言,学C语言。
C不强加你任何观点。
她不是面向对象(object oriented)的,但如果你愿意,你可以用C 语言进行面向对象的程序设计。
她不是函数语言(functional language),但如果你愿意,你可以用C语言进行函数语言范式程序设计。
大多数LISP语言和Scheme语言(一种完全的函数语言)的解释器和编译器就是用C语言编的!你用C语言进行链接表处理也许不如用LISP语言好用,但是你是可以用C语言进行链接表处理的。
汇编语言第六章
三.中断向量表
3. 设置或取出中断向量指令 (1) 设置中断向量指令 功能:把由AL指定的中断类型的中断向量DS:DX放入中
断向量表中。
(AH)= 25H
(AL)= 中断类型号
DS:DX = 中断向量 INT 21H
三.中断向量表
(2) 取出中断向量指令
功能:把AL中指定的中断类型的中断向量从中断
一、 WIN32编程基础
(2) 循环控制伪指令
格式:.WHILE 条件表达式 循环体 .ENDW 格式:.REPEAT 循环体 .UNTIL 条件表达式 格式:.CONTINUE 功能:终止本次循环, 开始下一次循环 格式:.BREAK 功能:退出当前循环
功能:实现循环结构
一、 WIN32编程基础
内中断的处理特点: ①中断类型号一般在指令中; ② 不受中断允许标志位IF的影响。
二、 中断源
2. 外中断 由外设控制器、协处理器等CPU以外的事件引起的中断, 称为外中断。 外中断的处理特点: ① 中断类型号由8259A提供,或由自制电路来提供;
② 受中断允许标志位IF的影响(IF=1,响应中断)。
个字节。
三.中断向量表
如:INT 4AH
中断向量地址 = 4AH*4 = 128H
DEBUG执行后, 用D命令查看: ―D0:0↙ … 执行INT 4AH时: IP=1805H CS=F000H IP F000: 1805 中断处理
0:128H
0:129H
05 18
0:12AH
0:12BH
00
F0 …
外设
二、 外设与主机传送的接口与信息
接口的组成:设备状态寄存器、设备控制寄存 器、数据寄存器。 I/O端口的地址空间:允许设置64K个8位端口 或32K个16位端口。 如:40H~43H时钟/定时器,60H~63H为 8255通讯芯片的接口。
罗云彬的Win32汇编教程
罗云彬的Win32汇编教程之一Win32汇编的环境和基础1.32位环境简介在Dos下编汇编程序,我们可以管理系统的所有资源,我们可以改动系统中所有的内存,如自己改动内存控制块来分配内存,自己修改中断向量表来截获中断等,对其他操作也是如此,如我们对键盘端口直接操作就可以把键盘屏蔽掉,可以这样来描述Dos系统:系统只有一个特权级别,在编程上讲,任何程序和操作系统都是同级的,所以在Dos下,一个编得不好的程序会影响其他所有的程序,如一个程序把键盘口中断关掉了,所有程序就都不能从键盘获得键入的数据,直到任何一个程序重新打开键盘为止,一个程序陷入死循环,也没有其他程序可以把它终止掉。
Dos下的编程思路是“单任务”的,你只要认为你的程序会按照你的流程一步步的执行下去,不必考虑先后问题(当然程序可能会被中断打断,但你可以认为它们会把环境恢复,如果中断程序没有把环境恢复,那是他们的错)。
在内存管理方式上,Dos汇编和Win32汇编也有很多的不同:Dos工作在实模式下,我们可以寻址1M 的内存,寻址时通过段寄存器来制定段的初始地址,每个段的大小为64K,超过1M的部分,就只能把他作为XMS使用,也就是说,只能用作数据存放使用而无法在其中执行程序。
而Windows在保护模式下执行,这里所有的资源对应用程序来说都是被“保护”的:程序在执行中有级别之分,只有操作系统工作在最高级--0级中,所有应用程序都工作在3级中(Ring3),在Ring3中,你无法直接访问IO端口,无法访问其他程序运行的内存,连向程序自己的代码段写入数据都是非法的,会在Windows的屏幕上冒出一个熟悉的蓝屏幕来。
只有对Ring0的程序来说,系统才是全开放的。
在内存方面,Windows使用了处理器的分页机制,使得对应用程序来说,所有的内存都是“平坦”的,你不必用一个段寄存器去指定段的地址,因为在保护模式下,段寄存器的含义是不同的(可以参见80386手册方面的书籍),你可以直接指定一个32位的地址来寻址4GB的内存。
Win32汇编语言简明教程
第一课基本概念我们先假设您已知道了如何使用MASM。
如果您还不知道的话,请下载win32asm.exe ,并请仔细研读其中所附带的文档资料。
好,如果您已准备就绪,我们这就开始吧!理论:WIN32 程序运行在保护模式下的,保护模式的历史可以追溯到 80286。
而今80286 已成为了历史。
所以我们将只把精力集中于 80386 及后续的X86 系列CPU。
Windows 把每一个 Win32 应用程序放到分开的虚拟地址空间中去运行,也就是说每一个应用程序都拥有其相互独立的 4GB 地址空间,当然这倒不是说它们都拥有 4GB 的物理地址空间,而只是说能够在 4GB 的范围内寻址。
操作系统将会在应用程序运行时完成 4GB 的虚拟地址和物理内存地址间的转换。
这就要求编写应用程序时必须格守 Windows 的规范,否则极易引起内存的保护模式错误。
而过去的 Win16 内存模式下,所有的应用程序都运行于同一个 4GB 地址空间,它们可以彼此"看"到别的程序的内容,这极易导致一个应用程序破坏另一个应用程序甚至是操作系统的数据或代码。
和 16 位 Windows 下的把代码分成 DATA,CODE 等段的内存模式不同,WIN32 只有一种内存模式,即 FLAT 模式,意思是"平坦"的内存模式,再没有 64K 的段大小限制,所有的 WIN32 的应用程序运行在一个连续、平坦、巨大的 4GB 的空间中。
这同时也意味着您无须和段寄存器打交道,您可以用任意的段寄存器寻址任意的地址空间,这对于程序员来说是非常方便的,这也使得用32位汇编语言和用C语言一样方便。
在Win32下编程,有许多重要的规则需要遵守。
有一条很重要的是:Windows 在内部频繁使用 ESI,EDI,EBP,EBX 寄存器,而且并不去检测这些寄存器的值是否被更改,这样当您要使用这些寄存器时必须先保存它们的值,待用完后再恢复它们,一个最显著的应用例子就是 Windows 的CallBack 函数中。
Windows编程基础新手入门
Windows编程基础基于Windows的编程方式有两种;一种是使用Windows的APIApplication Programming Interface,应用程序编程接口函数,通常用C/C++语言按相应的程序框架进行编程;这些程序框架往往就程序应用提供相应的文档、范例和软件开发工具包Software Development Kit,SDK,所以这种编程方式有时又称为SDK方式;另一种是使用“封装”方式,例如Visual C++的MFC方式,它是将SDK中的绝大多数函数、数据等按C++“类”的形式进行封装,并提供相应的应用程序框架和编程操作;事实上,无论是哪种编程方式,人们最关心的内容有三个:一是程序入口,二是窗口、资源等的创建和使用,三是键盘、鼠标等所产生的事件或消息的接收和处理;本章就来讨论这些内容;学习编程往往从简单的例子入手,例如一个C程序常有下列简单的框架代码:include <>int main{printf"Hello World\n"; / 输出 /return 0; / 指定返回值 /}事实上,该程序已包括C程序中最常用的include指令、必须的程序入口main函数、库函数printf调用和return语句;由于此程序是在早期的DOSDisk Operating System,磁盘操作系统环境的字符模型下运行的,因而printf函数所输出的都是字符流,也就是说,它在屏幕上输出一行文本“Hello World”;在Windows环境下,这里的屏幕就由控制台窗口来兼作,而基于Windows的上述C程序代码框架肯定是有所不同的;特别地,由于目前所在的Windows环境基本上都是32位,所以这里的Windows程序平台就是Win32,Windows编程可直接理解为是Win32编程;1.1.1 Windows等价程序等价的Windows程序可以写成:include <>int WINAPI WinMain HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int nCmdShow{MessageBox NULL, TEXT"Hello, World", TEXT"Hello", 0 ;return 0 ;}在深入剖析上述程序之前,先来看一看在Visual C++ 中的编辑、连接和运行的过程:①选择“开始”→“程序”→Microsoft Visual Studio →Microsoft Visual C++ ,运行Visual C++ ;第一次运行时,将显示如图所示的“每日提示”对话框;单击“下一条”按钮,可看到有关各种操作的提示;如果在“启动时显示提示”复选框中单击鼠标,去除复选框的选中标记“”,那么下一次运行Visual C++ ,将不再出现此对话框;单击“关闭”按钮关闭此对话框,进入Visual C++ 开发环境;②选择“文件”→“新建”菜单命令,打开应图“每日提示”对话框用程序向导,显示出“新建”对话框,如图所示;选择“工程”选项卡,从列表框中选中Win32 ApplicationWin32 应用程序项图中的标记1;③单击“位置”编辑框右侧的“浏览”按钮图中的标记2,从弹出的“选择目录”对话框指定项目所在的文件夹,如图所示图中的数字标记表示最经常的操作次序,下同;单击“确定”按钮,退出“选择目录”对话框,回到“新建”对话框中;需要说明的是,为了便于程序的管理和查找,本书所涉及的程序均放入Visual C++ 的工作文件夹“Visual C++程序”中,第1章程序放入子文件夹“第1章”中,第2章程序放入子文件夹“第2章”,依此类推;④在“新建”对话框的“工程名称”编辑框图中的标记3中,输入项目名称Ex_HelloMsg,保留“平台”下Win32复选框的默认“选中”状态,单击“确定”按钮进入下一步;⑤出现Win32 Application向导的“步骤1共1步”对话框,从中可选择要创建的应用程序类型:“一个空工程”、“一个简单的Win32程序”和“一个典型的"Hello World "程序”,如图所示;它们的区别在于:“一个空工程”仅创建Win32应用程序文件框架,不含任何代码;“一个简单的Win32程序”是在“一个空工程”基础上添加了程序框架有入口函数、include 指令等;“一个典型的‘Hello World’程序”在“一个简单的Win32程序”基础上增加了MessageBox函数调用,用来输出“Hello World”;图“新建”对话框“工程”选项卡图“选择目录”对话框⑥选中“一个空工程”,单击“完成”按钮,弹出“新建工程信息”对话框,如图所示;单击“确定”按钮,系统将按前面的选择自动创建此应用程序;图应用程序的向导对话框图“新建工程信息”对话框⑦再次选择“文件”→“新建”菜单命令,Visual C++将打开“新建”对话框并自动切换到“文件”选项卡,如图所示;在左侧的文件类型列表中选中C++ Source FileC++源文件,在右侧的“文件名”编辑框中输入“”或输入“”文件扩展名也可不输入,系统会自动添加cpp扩展名,cpp是C Plus Plus的缩写,是C++的意思;⑧单击“确定”按钮,系统将在创建的Win32项目工程Ex_HelloMsg中创建并添加一个新的文件,同时打开该文件窗口;现在可以在中输入前面例中的代码了;输完后,单击编译工具条上的“生成工具”按钮或直接按F7键,系统开始对Ex_HelloMsg项目工程中的文件进行编译、连接,同时在输出窗口中观察出现的内容,当出现errors, 0 warnings表示可执行文件已经正确无误地生成了;同时也可看到在文档窗口中所有代码的颜色都发生改变,这是Visual C++ 的文本编辑器所具有的语法颜色功能绿色表示注释,蓝色表示关键字等;⑨单击编译工具条上的“运行工具”按钮或直接按Ctrl+F5键,就可以运行刚刚生成的,结果如图所示;单击“确定”按钮,Hello对话框退出;图创建并添加程序文件图开发环境和运行结果1.1.2 头文件是一个include预处理指令开始,实际上在用C/C++编写的Windows应用程序的头部都可以看到这样的指令:include <>头文件是最主要的包含头文件,它还包含了其他一些Windows头文件; 例如:: 基本类型定义: 内核函数: 用户接口函数: 图形设备接口函数这些头文件定义了Windows的所有数据类型、函数调用、数据结构和符号常量,它们是Windows应用程序文档中的一个重要部分;1.1.3 程序入口函数在C/C++程序中,其入口函数都是main;但在Windows程序中,这个入口函数由WinMain 来代替;该函数是在中声明的,其原型如下:intWINAPIWinMainHINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd;可以看出,这个WinMain函数除了形参名、个数与main函数不同外,类型名也有了新的变化;下面就来分析:①WinMain函数被声明成为返回一个int值,同时WinMain函数名前还有WINAPI标识符的修饰;WINAPI是一种“调用约定”宏,它在中有如下定义:define WINAPI __stdcall所谓“调用约定”,就是指程序生成机器码后,函数调用的多个参数是按怎样的次序来传递,同时函数调用结束后堆栈由谁来恢复,以及编译器对函数名的修饰约定等的协议;函数调用约定“协议”有许多,其中由WINAPI宏指定的__stdcall是一个常见的协议,内容包括:参数从右向左压入堆栈;函数自身修改堆栈;机器码中的函数名前面自动加下划线,而函数后面接符号和参数的字节数;特别地,Visual C++的MFC方式却采用了__cdecl调用约定:参数从右向左压入堆栈;传递参数的内存栈由调用者来维护正因为如此可实现变参函数;机器码中的函数名只在前面自动加下划线;②WinMain函数的第一个和第二个参数都是HINSTANCE实例句柄类型;HINSTANCE中,H表示Handle,是“句柄”的意思;在Windows编程中,句柄是一个应用程序用来识别某些资源、状态、模块等的数字;由于句柄唯一标识着对应的资源、状态、模块等,因而使用句柄就是使调用相应的资源、状态、模块;当应用程序运行多次时,每一次都是应用程序的“实例”;由于同一个应用程序的所有实例都共享着应用程序的资源,因而程序通过检查hPrevInstance参数就可确定自身的其他实例是否正在运行;③WinMain函数的第三个参数lpCmdLine用来指定程序的命令行,其参数类型为LPSTR;但在中,却将其改为PSTR;这两种数据类型都是合法的,也都是指向字符串的指针类型;其中的STR是“STRING,字符串”的含义,是指以\0结尾的字符串,LP前缀表示“长指针”,在Win32中它与“P”前缀表示的“指针”含义相同;④WinMain函数的第四个参数nShowCmd用来指定程序最初显示的方式,它可以是正常、最大化或最小化来显示程序窗口;纵观上述参数和类型名可以发现它们的命名规则:●C/C++的类型名仍保留其小写,但新的类型都是用大写字母来命名;●参数名变量名都是采用“匈牙利表示法”的命名规则来定义的;它的主要方法是将变量名前后加上表示“类型”和“作用”的“前缀小写”,而变量名本身由“状态”、“属性”和“含义”等几个部分组成,每一个部分的名称可以是全称,也可以是缩写,但通常只有第一个字母是大写;例如,hPrevInstance则是由前缀h表示“句柄”类型+状态Prev表示“以前的”+属性Instance表示“实例”组成的;1.1.4 MessageBox函数MessageBox是一个Win32 API函数,用来弹出一个对话框窗口,显示短信息;该函数具有下列原型:int MessageBox HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType;其中,第一个参数hWnd用来指定父窗口句柄,即对话框所在的窗口句柄;第二、三个参数分别用来指定显示的消息内容lpText和对话框窗口的标题lpCaption,最后一个参数用来指定在对话框中显示的预定义的按钮和图标标识,它们是在定义的一组以MB_开始的常数组合;例如,下面是在中改变MessageBox的第四个参数;include <>int WINAPI WinMain HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int nCmdShow{MessageBox NULL, TEXT"Hello, World", TEXT"Hello",MB_ICONQUESTION | MB_ABORTRETRYIGNORE ;return 0 ;}程序运行后,结果如图所示;可见,MB_ICONQUESTION 用来指定在对话框中显示图标,而MB_ABORTRETRYIGNORE用来指定“终止”、“重试”和“忽略”按钮,类似这样的预定义标识还有很多,在以后讨论到MFC中的CWnd::MessageBox函数时还要讨论,故这里不再赘述;在程序中,调用MessageBox的实参中还涉及TEXT宏;在Windows编程中,TEXT宏是用来对UNICODE编码的字符串的支持;UNICODE是使用两个字节表示一个字符,这样单字节的ANSI字符和双字节的“汉字”的表示就统一起来了;在程序中使用图第四个参数的作用TEXT文本,无论在何Windows环境下均可显示正确的内容,而不会出现乱码的情形;另外,还有_TEXT 和_T宏等,在Visual C++中,它们的作用是等同的;窗口和消息MessageBox是通过创建的默认“窗口”来显示简单的信息:窗口标题、一行或多行文本、图标和按钮等;在Windows环境中,一个“窗口”就是屏幕上的一个矩形区域,它接收用户的输入,并以文本或图形方式来显示内容;事实上,“窗口”就是用户操作的区域界面,在编程中除创建等操作外,还要处理用户输入、窗口本身事件所产生的“消息”;1.2.1 程序框架代码为了能处理上述两个部分的内容:窗口创建和消息处理,Windows 提供了相应的程序框架,如下面的例子;include <>LRESULT CALLBACK WndProc HWND, UINT, WP ARAM, LP ARAM;客户区标题栏窗口边框其中,类名是已声明过的类的标识符,对象名可以有一个或多个,多个时要用逗号隔开;被定义的对象既可以是一个普通对象,也可以是一个数组对象或指针对象;例如:CStuscore one, Stu, Stus2;这时,one是类CStuscore的一个普通对象,Stu和Stus分别是该类的一个指针对象和对象数组;若对象是一个指针,则还可像指针变量那样进行初始化,例如:CStuscore two = &one;可见,在程序中,对象的使用和变量是一样的,只是对象还有成员的访问等手段;3.对象成员的访问一个对象的成员就是该对象的类所定义的数据成员和成员函数;访问对象的成员变量和成员函数与访问一般结构的变量的方法是一样的;对于普通对象,其访问格式如下:<对象名>.<成员变量><对象名>.<成员函数><参数表>例如,用来调用对象one中的成员函数getName,Stus0.getNo用来调用对象数组元素Stus0中的成员函数getNo;要注意,由于类的封装性,每个成员均有声明的访问属性,一个类对象只能访问该类的公有型成员,而对于私有型成员则不能访问,例如getName和getNo等公有成员可以由对象通过上述方式来访问,但strName、strStuNo、fScore等私有成员不能被对象来访问;若对象是一个指针,则对象的成员访问格式如下:<对象名>-><成员变量><对象名>-><成员函数><参数表>“->”是另一个表示成员的运算符,它与“.”运算符的区别是:“->”用来表示指向对象的指针的成员,而“.”用来表示一般对象的成员;需要说明的是,下面的两种表示是等价的对于成员函数也适用:<对象指针名>-><成员变量><对象指针名>.<成员变量>例如,two.getName与two->getName等价;可见,在C++中,类实际上是一种新的数据类型,它是对某一类对象的抽象;如同变量一样,用“类”也可定义一个对象,此时的对象称为类的实例;1.3.2 构造函数和析构函数事实上,一个类总有两种特殊的成员函数:构造函数和析构函数;构造函数的功能是在创建对象时,给数据成员赋初值,即给对象初始化;析构函数的功能是用来释放一个对象,在对象删除前,用它来做一些内存释放等清理工作,它与构造函数的功能正好相反;1.构造函数C++规定,在类的定义中是不能对数据成员进行初始化的;为了能给数据成员设置某些初值,这时就要使用类的特殊成员函数——构造函数;构造函数的最大特点是在对象建立时它会被自动执行,因此用于变量、对象的初始化代码一般放在构造函数中;C++规定,一个类的构造函数必须与相应的类同名,它可以带参数,也可以不带参数,与一般的成员函数定义相同,可以重载,也可以有默认的形参值;例如:include <>class CPerson{public:CPersonchar str, float h, float w // A:构造函数{strcpyname, str; height = h; weight = w;}CPersonchar str // B:构造函数{strcpyname, str;}CPersonfloat h, float w = 120; // C:构造函数public:void print{cout<<"姓名:"<<name<<"\t身高:"<<height<<"\t体重:"<<weight<<endl;}private:char name20; // 姓名float height; // 身高float weight; // 体重};CPerson::CPersonfloat h, float w{height = h; weight = w;}int main{CPerson one"DING";;CPerson two170, 130;;CPerson three"DING", 170, 130;;return 0;}include后面的是C++编译器自带的文件,称为C++库文件,它定义了标准输入/输出流的相关数据及其操作;cout表示标准输出流对象屏幕,“<<”是插入符,它将后面的内容插入到cout 中,即输出到屏幕上;程序运行的结果为:姓名:DING 身高:–+008 体重:–+008姓名:烫烫烫烫烫烫烫烫烫烫身高:170 体重:130姓名:DING 身高:170 体重:130分析和说明:①类CPerson定义了3个重载的构造函数程序中用A、B、C标明,这些构造函数的重载必须按其规定进行定义,要么参数个数不同,要么参数个数相同,但参数类型不相同;其中,构造函数CPersonfloat h, float w = 120,不仅设置了形参w的默认值,而且还将该构造函数的声明在类中进行,其定义在类体外实现;②在主函数main中,对象one的初始化等价于"DING",因而调用的是B构造函数,此时对象的私有数据成员name设定了初值“DING”,而height和weight初值没有指定,它们的初值取决于对象的存储类型,可能是默认值或无效值;③对象two的初始化等价于170, 130,因而调用的是C构造函数,此时对象的私有数据成员height和weight初值分别设定为170、130,而name初值没有指定,它可能是默认值或无效值;④对象three的初始化等价于"DING", 170, 130,因而调用的是A构造函数,此时对象的私有数据成员name、height和weight初值分别设定为"DING"、170和130;可见,构造函数提供了对象的初始化方式;若没有定义任何构造函数,则编译自动为类隐式生成一个不带任何参数的默认构造函数,由于函数体是空块,因此默认构造函数不进行任何操作,仅仅为了对象创建时的语法需要;例如,对于CPerson类来说,默认构造函数的形式如下:CPerson // 默认构造函数的形式{ }默认构造函数的目的是使下列对象定义形式合法:CPerson one; // 即: ; 会自动调用默认构造函数此时,由于对象one没指定任何初值,因而编译会自动调用类中隐式生成的默认构造函数对其初始化;若当类定义中指定了构造函数,则隐式的默认构造函数不再存在,因此,若对于前面定义的CPerson类来说,若有:C Person four; // 错误则因为找不到默认构造函数而出现编译错误;此时,在类中还要给出默认构造函数的具体定义,即定义一个不带任何参数的构造函数,称为显式的默认构造函数,这样才能对four进行定义并初始化;另外,构造函数的访问属性必须是公有型public,否则上述的类对象定义也是错误的;2.析构函数与构造函数相对应的是析构函数Destructor;析构函数是C++类中另一个特殊的成员函数,它只是在类名称前加上一个“~”符号逻辑非,以与构造函数功能相反;其格式如下:< ~类名>{ … }当对象的生存期结束后,或者当使用delete释放由new来分配动态内存的对象时,析构函数会被自动调用;这样,数据成员尤其是用new为其开辟的内存空间的释放代码就可放入析构函数的函数体中,以便对象消失后自动调用;需要说明的是:①每一个类最多只能有一个析构函数,且应为public,否则类实例化后无法自动调用析构函数进行释放,但不能被重载,没有任何参数,也不返回任何值,函数名前也不能有任何关键词包括void;例如:class CPerson{public:…~CPerson { }// 析构函数…};②与类的其他成员函数一样,析构函数的定义也可在类体外进行,但必须指明它所属的类,且在类体中还必须有析构函数的声明;例如:。
Win32 Api编程指南
HINSTANCE hInstance 程序执行模块的句柄。( 内存中的.exe 文件 )。
HINSTANCE hPrevInstance 在 Win32 程序中总为 NULL。
LPSTR lpCmdLine 一个字符串的命令行参数。不包括程序名。
int nCmdShow 会解释。
hInstance 主要用来装载资源和执行一些基于其它模块的功能。模块是指装载到程序中的 exe 或者 dll 文 件。在本书的大部分( 不是全部 )内容中,它们都是指 exe 文件。
重要的说明
在全书中,通常我会指出一些非常重要的东西,这些都是必读的。因为它们常常把人弄得糊里糊涂,如果 您不读这些东西,很有可能也会身陷其中。
首先: 范例压缩包里的源代码是必读的!我没有在书中包含全部的代码,而只包含了那些与我们当前讨论的内容 有关的代码片断。如果您想详细了解代码在程序中的体现,就必须去参看压缩包内提供的源代码。 其次: 通读所有的内容!如果您在书中的某个部分有什么疑问,请耐心的读下去,也许不久,在后面的部分中就 会找到答案。如果您非想要立刻就弄清楚这个问题,至少也要保证,在通过 IRC 或者 Email 来寻求答案之前, 你已经浏览或者搜索了其余的部分了。 另外,请记住,题目 A 中涉及的问题,有可能在 B 或者 C 甚至 L 中才会做出解答,所以还是先泛读一遍比 较好。 好了,以上就是我想说的全部注意事项了,接下来让我们看一些实际的例子吧。
接下来是跟在 LP 后面的一个表示常量的字符 C,LPCSTR 表示一个指向字符串常量的长指针,它指向的内容 是不可修改的。LPSTR 是指向字符串的长指针,没有 const 关键字,它指向的内容是可以修改的。
win32界面编程 实例
win32界面编程实例
Win32界面编程是指使用Win32 API来创建Windows应用程序
的用户界面。
下面我将从不同角度给出一些Win32界面编程的实例。
1. 创建窗口,使用Win32 API可以创建一个基本的窗口应用程序。
首先需要注册窗口类,然后创建窗口并处理窗口消息。
通过设
置窗口类的属性和消息处理函数,可以实现窗口的基本功能,比如
响应用户输入、绘制图形等。
2. 控件和布局,Win32 API提供了一系列控件,比如按钮、文
本框、列表框等,可以通过创建这些控件来构建丰富的用户界面。
同时,可以使用布局管理技术来控制控件的位置和大小,以实现界
面的美观和合理布局。
3. 图形绘制,Win32 API允许开发者直接操作图形设备接口(GDI),从而实现自定义的图形绘制功能。
通过GDI可以绘制各种
图形、文本和图像,实现丰富多彩的界面效果。
4. 用户交互,Win32界面编程可以实现丰富的用户交互功能,
比如鼠标点击、键盘输入、菜单操作等。
通过响应用户的交互行为,
可以让应用程序更加灵活和易用。
5. 窗口管理,Win32 API提供了丰富的窗口管理功能,比如最大化、最小化、关闭窗口等。
开发者可以通过这些功能来管理应用程序的窗口,提升用户体验。
总之,Win32界面编程可以实现丰富多彩的Windows应用程序界面。
开发者可以通过灵活运用Win32 API提供的功能,创建出符合自己需求的界面效果。
希望以上实例可以帮助你更好地理解
Win32界面编程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//*******************************************************************
// 工程:easywin
// 文件:easywin.cpp
//
内容:一个基本的
Win32
程序
//*******************************************************************
wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "EasyWin"; //注册窗口类 RegisterClass( &wc );
//创建主窗口 hwnd = CreateWindow( "EasyWin", //窗口类名称 "一个基本的 Win32 程序", //窗口标题 WS_OVERLAPPEDWINDOW, //窗口风格,定义为普通型 100, //窗口位置的 x 坐标 100, //窗口位置的 y 坐标 400, //窗口的宽度 300, //窗口的高度 NULL, //父窗口句柄 NULL, //菜单句柄 hInstance, //应用程序实例句柄 NULL ); //窗口创建数据指针 if( !hwnd ) return FALSE; //显示并更新窗口 ShowWindow( hwnd, nCmdShow );
UpdateWindow( hwnd ); return TRUE; } //****************************************************************** //函数:WinProc() //功能:处理主窗口消息 //****************************************************************** LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { case WM_KEYDOWN://击键消息 switch( wParam ) { case VK_ESCAPE: MessageBox(hWnd,"ESC 键按下了!","Keyboard",MB_OK); break; } break; case WM_RBUTTONDOWN://鼠标消息 { MessageBox(hWnd,"鼠标右键按下了!","Mouse",MB_OK);
#include <windows.h>
#include <windowsx.h>
//函数声明 BOOL InitWindow( HINSTANCE hInstance, int nCmdShow ); LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); //******************************************************************* //函数:WinMain() //功能:Win32 应用程序入口函数。创建主窗口,处理消息循环 //******************************************************************* int PASCAL WinMain( HINSTANCE hInstance, //当前实例句柄 HINSTANCE hPrevInstance, //前一个实例句柄 LPSTR lpCmdLine, //命令行字符 int nCmdShow) //窗口显示方式 { MSG msg; //创建主窗口 if ( !InitWindow( hInstance, nCmdShow ) ) return FALSE; //进入消息循环: //从该应用程序的消息队列中检取消息,送到消息处理过程, //当检取到 WM_QUIT 消息时,退出消息循环。 while (GetMessage(&msg, NULL, 0, 0)) {
程序输入完毕,即可编译执行。在窗口中击鼠标键或按 ESC 键时,会弹出一个对话框 以表示你的操作。
其实,这个程序可以看成是所有 Win32 应用程序的框架,在以后所有的程序中,你会 发现它们都是在这个程序的基础之上再添加代码。
WinMain()函数
WinMain()函数是应用程序开始执行时的入口点,通常也是应用程序结束任务退出时的 出口点。它与 DOS 程序的 main()函数起同样的作用,有一点不同的是,WinMain()函数必须 带有四个参数,它们是系统传递给它的。WinMain()函数的原型如下:
打开 Visual C++ 6.0。
选择 File 菜单的 New,在出现的对话框中,选择 Projects 栏目(新建工程),并点取其 下的 Win32 Application 项,表示使用 Win32 环境创建应用程序。先在 Locatin(路径)中填 入“c:\”,然后在 Project Name(项目名称)中填入“EasyWin”,其它按照缺省设置)。单击 OK 按钮。
break; } case WM_PAINT://窗口重画消息 { char hello[]="你好,我是 EasyWin !"; HDC hdc; PAINTSTRUCT ps; hdc=BeginPaint( hWnd,&ps ); //取得设备环境句柄 SetTextColor(hdc, RGB(0,0,255)); //设置文字颜色 TextOut( hdc, 20, 10, hello, strlen(hello) );//输出文字 EndPaint( hWnd, &ps ); //释放资源 break; } case WM_DESTROY://退出消息 PostQuitMessage( 0 );//调用退出函数 break; } //调用缺省消息处理过程 return DefWindowProc(hWnd, message, wParam, lParam); }
TranslateMessage(&msg); DispatchMessage(&msg); } //程序结束 return msg.wParam; } //****************************************************************** //函数:InitWindow() //功能:创建窗口。 //****************************************************************** static BOOL InitWindow( HINSTANCE hInstance, int nCmdShow ) { HWND hwnd; //窗口句柄 WNDCLASS wc; //窗口类结构 //填充窗口类结构 wc.style = CS_VREDRAW | CS_HREDRAW; wc.lpfnWndProc = (WNDPROC)WinProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION ); wc.hCursor = LoadCursor( NULL, IDC_ARROW );
这里有两个概念,一个是实例,一个是句柄。实例代表的是应用程序执行的整个过程和 方法,一个应用程序如果没有被执行,只是存在 于磁盘上,那么就说它是没有被实例化的; 只要一执行,则说该程序的一个实例在运行。句柄,顾名思义,指的是一个对象的把柄。在 Windows 中,有各种各 样的句柄,它们都是 32 位的指针变量,用来指向该对象所占据的内 存区。句柄的使用,可以极大的方便 Windows 管理其内存中的各种对象。
一个最简单的 Win32 程序
在以前的 C 语言编程中,一个最简单的程序可以只有两行。 void main(void)
{ printf "Hello World!"; }
而要实现同样功能的 Windows 程序却最少也要写几十行,这并不是说明 Windows 应 用程序效率低下,难于掌握,只是说明程序在 Windows 环境 下有更丰富的内涵。Windows 程序的效率其实不低,在所有的 Windows 应用程序中,都有一个程序初始化的过程,这得 用上几十条语句,这段初始化的 代码对于任何 Windows 应用程序而言,都是大同小异的。 下面以一个实现最简单功能的程序 EasyWin 为例,说明 Windows 程序的基本框架。
Win32 编程基础
尽管 Windows 应用程序千变万化,令人眼花缭乱,但,消息机制和窗口过程却始终它 们的基础,掌握了这两项技术,也就相当于把握住了问题的关键。