传递给 CreateWindow 和 RegisterClass 的 HINSTANCE 有什么用?



       译者按:老汉当初学习 Windows 编程的时候就对此问题有过疑惑,后来明白了,却懒得写一篇总结性的东西。这是在 The Old New Thing 的 Blog 上发现的,翻译过来,权且为新手释疑。原文的链接为 http://blogs.msdn.com/oldnewthing/archive/2005/04/18/409205.aspx。

       CreateWindow 函数和 RegisterClass 函数(译者注:以及这两个函数相应的 Ex 后缀版本)中很少被人理解的一个参数是 HINSTANCE(或者作为参数传递或者作为 WNDCLASS 结构的一部分)。

       窗口类名不足以唯一地标志窗口类。每个进程有自己的窗口类列表,窗口类列表中的每一项都由一个实例句柄和一个类名字组成。例如,如果一个程序有两个 DLL,每个都注册了一个名为“MyClass”的窗口类,并且将 DLL 的句柄作为 HINSTANCE 传递,则窗口类列表看起来就象这样:

HINSTANCE Class name
1 USER32.DLL Static
2 USER32.DLL Button
3 USER32.DLL ListBox
4 USER32.DLL ComboBox
5 USER32.DLL Edit
6 A.DLL MyClass
7 B.DLL MyClass

当要创建窗口时,每个模块传递它自己的 HINSTANCE,窗口管理器使用实例句柄和窗口类名的组合来寻找窗口类。

CreateWindow("MyClass", ..., hinstA, ...); // 创建窗口 6
CreateWindow("MyClass", ..., hinstB, ...); // 创建窗口 7
CreateWindow("MyClass", ..., hinstC, ...); // 失败

这就是为什么多个 DLL 都创建名为“MyClass”的类可以成功,实例句柄用来将它们区别开来。

       但是上述规则有一个例外。如果在你注册窗口类时指定了 CS_GLOBALCLASS 标志,那么窗口管理器在寻找你的窗口类时将忽略实例句柄。所有的 USER32 窗口类都被注册为全局的。因而,下面所有的调用都会创建 USER32 的编辑框控件:

CreateWindow("edit", ..., hinstA, ...);
CreateWindow("edit", ..., hinstB, ...);
CreateWindow("edit", ..., hinstC, ...);

       如果你要注册一个用在其他模块的对话框里的窗口类,你就需要注册为 CS_GLOBALCLASS,因为像我们先前看到的,在对话框创建过程中,创建控件执行的内部 CreateWindow 调用会把对话框的 HINSTANCE 用作 HINSTANCE 参数。因为对话框的实例句柄通常是创建该对话框的 DLL(因为相同的 HINSTANCE 要用来寻找对话框模板),不使用 CS_GLOBALCLASS 标志注册意味着寻找窗口类时将不能找到该类,因为它注册于提供该窗口类的 DLL 的实例句柄名下而不是使用它的那个。

在16 位 Windows 中,实例句柄还要用来做其他事情,但在 Win32 里已经没有关系了。

      一个常见的错误是在注册窗口类时传递一些其他的 HINSTANCE 进去(典型地,主执行程序的)。现在了解了 HINSTANCE 的用途,你就应该能够解释用错误的 HINSTANCE 注册窗口类的后果了。


转载自:http://www.somedoc.net/?p=308

—————————————————————————————————————————————————————————————————————————————

注:进程和程序的区别

①进程是程序的一次执行,属于动态概念,而程序是一组有序的指令,是一种静态概念。但进程离开了程序也就失去了存在的意义。

②一个进程可以执行一个或几个程序。反之,同一程序可能由几个进程同时执行。

③程序可作为软件资源长期保留,而进程是程序的一次执行过程,是暂时的。进程具有生命期。

④进程具有并发性,能与其它进程并发运行。而程序不具备这种特征。

⑤进程是一个独立的运行单位,也是系统进行资源分配和调度的一个独立单位。因此,进程具有独立性,但有时进程间又具有相互制约性。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
windows api 做的贪吃蛇 #include #include"resource.h" #include"Node.h" #include #include TCHAR szAppname[] = TEXT("Snack_eat"); #define SIDE (x_Client/80) #define x_Client 800 #define y_Client 800 #define X_MAX 800-20-SIDE //点x的范围 #define Y_MAX 800-60-SIDE //点y的范围 #define TIME_ID 1 #define SECOND 100 #define NUM_POINT 10 //点的总个数 #define ADD_SCORE 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; //窗口句柄 MSG msg; //消息 WNDCLASS wndclass; //窗口类 HACCEL hAccel;//加速键句柄 wndclass.style = CS_HREDRAW | CS_VREDRAW; //窗口的水平和垂直尺寸被改变时,窗口被重绘 wndclass.lpfnWndProc = WndProc; //窗口过程为WndProc函数 wndclass.cbClsExtra = 0; //预留额外空间 wndclass.cbWndExtra = 0; //预留额外空间 wndclass.hInstance = hInstance; //应用程序的实例句柄,WinMain的第一个参数 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //设置图标 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //载入预定义的鼠标指针 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置画刷 wndclass.lpszMenuName = szAppname; //设置菜单 wndclass.lpszClassName = szAppname; //设置窗口类的名字 if (!RegisterClass(&wndclass))//注册窗口类 { MessageBox(NULL, TEXT("这个程序需要windows NT!"), szAppname, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppname, TEXT("Snack_eat"),//CreateWindow函数调用时,WndProc将受到WM_CREATE WS_OVERLAPPEDWINDOW&~WS_THICKFRAME& ~WS_MAXIMIZEBOX,//普通的层叠窗口&禁止改变大小&禁止最大化 CW_USEDEFAULT, //初始x坐标(默认) CW_USEDEFAULT, //初始y坐标 x_Client, //初始x方向尺寸 770 y_Client, //初始y方向尺寸 750 NULL, //父窗口句柄 NULL, //窗口菜单句柄 hInstance, //程序实例句柄 WinMain函数中第二个参数 NULL); //创建参数 ShowWindow(hwnd, iCmdShow);//显示窗口,iCmdShow是WinMain的第四个参数,决定窗口在屏幕中的初始化显示形式,例:SW_SHOWNORMAL表示正常显示 UpdateWindow(hwnd);//使窗口客户区重绘,通过向WndProc发送一条WM_PAINT消息而完成的 hAccel = LoadAccelerators(hInstance, szAppname);//加载加速键 while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }/* while (GetMessage(&msg, NULL, 0, 0))//GetMessage函数从消息队列中得到消息,填充msg。如果msg.message等于WM_QUIT,返回0,否则返回非0 { TranslateMessage(&msg);//将msg返回给windows已进行某些键盘消息的转换 DispatchMessage(&msg);//将msg再次返回给windows }*/ return msg.wParam;//msg.wParam是PostQuitMessage函数的参数值,通常是0 } ...
最简单的winmain程序 #include #include LRESULT CALLBACK WinSunProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { HDC hdc; switch(uMsg) { case WM_CHAR: char szChar[20]; sprintf(szChar,"char is %d",wParam); MessageBox(hwnd,szChar,"weixin",0); break; case WM_LBUTTONDOWN: MessageBox(hwnd,"mouse clicked","weixin",0); hdc=GetDC(hwnd); TextOut(hdc,0,50,"计算机编程语言培训",strlen("计算机编程语言培训")); ReleaseDC(hwnd,hdc); break; case WM_PAINT: PAINTSTRUCT ps; hdc=BeginPaint(hwnd,&ps); TextOut(hdc,0,0,"维新培训",strlen("维新培训")); EndPaint(hwnd,&ps); break; case WM_CLOSE: if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO)) DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { WNDCLASS wndcls; wndcls.cbClsExtra=0; wndcls.cbWndExtra=0; wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wndcls.hCursor=LoadCursor(NULL,IDC_CROSS); wndcls.hIcon=LoadIcon(NULL,IDI_ERROR); wndcls.hInstance=hInstance; wndcls.lpfnWndProc=WinSunProc; wndcls.lpszClassName="Weixin2003"; wndcls.lpszMenuName=NULL; wndcls.style=CS_HREDRAW | CS_VREDRAW; RegisterClass(&wndcls); HWND hwnd=CreateWindow("Weixin2003","北京维新科学技术培训中心",WS_OVERLAPPEDWINDOW,0,0,600,400,NULL,NULL,hInstance,NULL); DWORD dwStyle=GetWindowLong(hwnd, GWL_STYLE); dwStyle&=~(WS_SIZEBOX|WS_MAXIMIZEBOX|WS_MINIMIZEBOX); SetWindowLong(hwnd, GWL_STYLE, dwStyle); ShowWindow(hwnd,SW_SHOWNORMAL); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
该代码是基于vc的数据可视化功能 #include #include LRESULT CALLBACK WangProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { WNDCLASS wndcls; wndcls.cbClsExtra=0; wndcls.cbWndExtra=0; wndcls.hbrBackground=NULL;//(HBRUSH)GetStockObject(BLACK_BRUSH); wndcls.hCursor=LoadCursor(NULL,IDC_NO); wndcls.hIcon=LoadIcon(NULL,IDI_ERROR); wndcls.hInstance=hInstance; wndcls.lpfnWndProc=WangProc; wndcls.lpszClassName="王朝帅"; wndcls.lpszMenuName=NULL; wndcls.style=CS_VREDRAW | CS_PARENTDC/* | CS_HREDRAW*/; RegisterClass(&wndcls); HWND hwnd; hwnd=CreateWindow("王朝帅","安徽大学 计算机科学与技术学院 王朝帅",WS_OVERLAPPEDWINDOW, 50,50,600,400,0,0,0,NULL); ShowWindow(hwnd,SW_SHOWNORMAL); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg,hwnd,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WangProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_CHAR: char szChar[20]; sprintf(szChar,"char is '%c'",wParam); MessageBox(hwnd,szChar,"朝帅作品",MB_OK); break; case WM_LBUTTONDOWN: MessageBox(hwnd,"mouse clicked","朝帅作品",MB_OK); HDC hdc; hdc=GetDC(hwnd); TextOut(hdc,0,50,"MFC学习中心--朝帅作品",strlen("MFC学习中心--朝帅作品")); ReleaseDC(hwnd,hdc); break; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; hDC=BeginPaint(hwnd,&ps); TextOut(hDC,0,0,"MFC培训",strlen("MFC培训")); EndPaint(hwnd,&ps); break; case WM_CLOSE: if(IDYES==MessageBox(hwnd,"是否真的结束?","朝帅作品",MB_YESNO)) { DestroyWindow(hwnd); } break; case WM_DESTROY: PostQuitMessage(1); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; }
实验1 Windows编程基础实验报告 一、实验目的和要求 (1)创建一个Win32应用程序Ex_SDK,在程序中构造一个编辑框控件和一个按钮。 (2)编辑框用于输入一元二次方程的系数,当单击"计算"按钮,获取方程系数得的根 通过TextOut显示在窗口客户区中。 二、实验环境 操作系统:Windows 2000 编译器:Visual C++ 6.0的开发环境 三、实验准备和说明 (1)具备知识:简单的SDK编程基础。 (2)准备本次上机所需要的程序。 (3)创建本次实验工作文件夹"…\Visual C++程序\实验\实验1" 四、实验内容和步骤 1.启动Visual C++ 6.0 打开计算机,启动Visual C++ 6.0系统。 2.创建工程并添加代码 选择"文件" "新建"菜单命令,打开应用程序向导,显示出"新建"对话框。单击"工程"标 签,从列表框中选中Win32 Application(Win32 应用程序)项。在工程名称框中输入Win32应用程序项目名称Ex_SDK。单击浏览按钮... 将工程定位到文件夹 "…\Visual C++ 6.0程序\实验\实验1"。 单击"确定"按钮继续。在向导第一步对话框中,选中An empty project(一个空的工程)项。单击"完成"按钮,系统将显示AppWizard(应用程序向导 )的创建信息,单击"确定"按钮,系统将自动创建此应用程序。 再次选择"文件" "新建"菜单命令,显示出"新建"对话框。单击"文件"标签,在左边的列 表框中选择C++ Source File项,在右边的"文件"下的编辑框中输入Ex_SDK.cpp,单击"确定"按钮。 在打开的文档窗口中输入下面的代码: #include <windows.h> #include <math.h> #include <stdio.h> // 求一元二次方程的根,函数返回根的个数 int GetRoot(float a, float b, float c, double *root) { double delta, deltasqrt; delta = b*b - 4.0 * a * c; if (delta<0.0) return 0; // 无根 deltasqrt = sqrt(delta); if (a!=0.0) { root[0] = (-b + deltasqrt)/(2.0 * a); root[1] = (-b - deltasqrt)/(2.0 * a); } else if (b!=0.0) root[0] = root[1] = -c/b; else return 0; if (root[0] == root[1]) return 1; else return 2; } char str[80]; LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); // 窗口过程 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hwnd ; // 窗口句柄 MSG msg ; // 消息 WNDCLASS wndclass ; // 窗口类 wndclass.style = CS_HREDRAW " CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = "SDKWin"; // 窗口类名 if (!RegisterClass (&wndclass)) // 注册窗口 { MessageBox (NULL, "窗口注册失败!", "HelloWin", 0) ; return 0 ; } // 创建窗口 hwnd = CreateWindow ("SDKWin", // 窗口类名 "实验1——Windows编程基础", // 窗口标题 WS_OVERLAPP
好的,下面是一个简单的 Win32 API 程序,它演示了如何创建一个窗口,并在窗口中显示文本: ```c++ #include <windows.h> // 窗口过程 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); // 绘制文本 TextOut(hdc, 10, 10, "Hello, world!", 13); EndPaint(hwnd, &ps); } return 0; } return DefWindowProc(hwnd, uMsg, wParam, lParam); } // 程序入口点 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // 注册窗口类 WNDCLASS wc = { 0 }; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = "MyWindowClass"; RegisterClass(&wc); // 创建窗口 HWND hwnd = CreateWindow( "MyWindowClass", "My Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (hwnd == NULL) { MessageBox(NULL, "Failed to create window", "Error", MB_OK | MB_ICONERROR); return 1; } // 显示窗口 ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 消息循环 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } ``` 这个程序使用了 Win32 API 来创建一个窗口,并在窗口中显示了文本。在程序入口点 `WinMain` 中,首先注册了一个窗口类,然后创建了一个窗口,并显示出来。接着进入消息循环,等待消息的到来,然后处理消息。在窗口过程 `WindowProc` 中,处理了窗口销毁和绘制消息。在绘制消息中,使用了 `TextOut` 函数来绘制文本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值