您的位置:首页 > 其它

win32 的DLL中创建windows窗口

2012-12-12 11:25 169 查看
因工作需要,需要写一个DLL,在DLL中创建windows窗口,网上有很多关于DLL创建窗口的文章,不过是基于MFC的, 却鲜见直接用win32的DLL创建的。研究调试了一下,实现了在win32 DLL中创建窗口,集结成文,分享一下。
实际上,用win32 DLL创建窗口有一个问题:
1.CreateWindow用到的HINSTANCE从哪里来?
答:使用DllMain中的hModule
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
hModule虽然是HANDLE,不能直接使用,强转即可。
g_hIntance= (HINSTANCE)hModule;
Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。
HMODULE 是代表应用程序载入的模块,win32系统下通常是被载入模块的线性地址
HINSTANCE 在win32下与HMODULE是相同的东西,在Win32下还存在主要是因为win16。
这是来自百度百科的解释【1】。
显然HINSTANCE和HANDLE是两个玩意,但这里却可以强转,并成功了。调试过程中,看到的值
hModule 是0x10000000
g_hIntance是0x10000000,成员unused的值是9460301,
显然,hModule和g_hInstance 是模块的起始地址。
LoadLiibrary返回的HINSTANCE值也是模块的起始地址。
难道2者有什么关联?不细说了,有空研究。

实际运行中,我是将win32 windows的模板代码直接拷过来,直接白WinMain作为一个函数给DLL调用了,但不完善,遇到以下问题:
1. 编译错误。一些宏没有了,需要将resource.h、资源文件和一些资源如ico拷过来。
2. 窗口显示不了。跟了一下ShowWindow,发现返回值是0,表示窗口隐藏,原来是由nCmdShow决定的,由于没有值,就全部给了NULL或0。给nCmdShow改成1之后就OK了。
贴一下代码:
//dllmain
// ad.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "ad.h"
#include "winform.h"
#include <process.h>

HINSTANCE g_hIntance;
int flag=0;

void c(void *)
{
flag=1;
MyCreateWindow(g_hIntance,NULL,NULL,1);
return;
}

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
g_hIntance= (HINSTANCE)hModule;
if(flag==0){
_beginthread(c,NULL,NULL);
flag=1;
}
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

// 这是导出变量的一个示例
AD_API int nad=0;

// 这是导出函数的一个示例。
AD_API int fnad(void)
{
return 42;
}

// 这是已导出类的构造函数。
// 有关类定义的信息,请参阅 ad.h
Cad::Cad()
{
return;
}

//winform.h
// ad.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;
// 当前实例
TCHAR szTitle[MAX_LOADSTRING];
// 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];
// 主窗口类名

BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()

// 此代码模块中包含的函数的前向声明:
ATOM
MyRegisterClass(HINSTANCE hInstance);
BOOL
InitInstance(HINSTANCE, int);
LRESULT CALLBACK
WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK
About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY MyCreateWindow(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{

// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;

// 初始化全局字符串
//LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
//LoadString(hInstance, IDC_AD, szWindowClass, MAX_LOADSTRING);
ATOM r=MyRegisterClass(hInstance);

// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_AD);

//
主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

return 0;
}

//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
// 注释:
//
// 仅当希望在已添加到 Windows 95 的
// “RegisterClassEx”函数之前此代码与 Win32 系统兼容时,
// 才需要此函数及其用法。调用此函数
// 十分重要,这样应用程序就可以获得关联的
// “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style
= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc
= (WNDPROC)WndProc;
wcex.cbClsExtra
= 0;
wcex.cbWndExtra
= 0;
wcex.hInstance
= hInstance;
wcex.hIcon
= LoadIcon(hInstance, (LPCTSTR)IDI_AD);
wcex.hCursor
= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground
= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName
= (LPCTSTR)IDC_AD;
wcex.lpszClassName
= _T("TEST");
wcex.hIconSm
= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);

return RegisterClassEx(&wcex);
}

//
// 函数: InitInstance(HANDLE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;

hInst = hInstance; // 将实例句柄存储在全局变量中

hWnd = CreateWindow(_T("TEST"), _T("TEST"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

if (!hWnd)
{
DWORD r=GetLastError();
return FALSE;
}

BOOL r1=ShowWindow(hWnd, nCmdShow);
//DWORD r=GetLastError();
r1=UpdateWindow(hWnd);
//r=GetLastError();

return TRUE;
}

//
// 函数: WndProc(HWND, unsigned, WORD, LONG)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND
- 处理应用程序菜单
// WM_PAINT
- 绘制主窗口
// WM_DESTROY
- 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

//*********************

//**********************
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// “关于”框的消息处理程序。
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}

参考文献:
1.HINSTANCE http://baike.baidu.com/view/2434154.htm
本文出自 “一些想法” 博客,请务必保留此出处/article/7264960.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: