【转】win32 的DLL中创建windows窗口

转自:https://blog.51cto.com/wangyw/1071967

       因工作需求,需要写一个DLL,并在其中创建windows窗口,网上有很多关于DLL创建窗口的文章,不过都是基于MFC的, 却鲜见直接用win32的DLL创建的。经过研究调试,实现了在win32 DLL中创建窗口,总结成文,分享一下。

用win32 DLL创建窗口有一个问题:

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 是模块的起始地址。

      LoadLibrary返回的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值