win32 的DLL中创建windows窗口

30 篇文章 1 订阅

因工作需要,需要写一个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

本文出自 “一些想法” 博客,请务必保留此出处http://wangyw.blog.51cto.com/4075460/1071967

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值