本节内容

1、功能描述

对话框可以分为modal和modeless两种。

2、在Win32 Dll中创建modal对话框

在一个Win32Dll中创建modal对话框非常简单,我们都知道,Win32函数DialogBox能够创建一个modal对话框,并且modal对话框的消息是独立于主程序消息循环的,所以可以直接在Dll内部建立对话框自己的窗口过程。下面就是一个在Win32 Dll中创建modal对话框的示例:

//name: Modal_Dialog.cpp
#include<windows.h>
#include"resource.h"
BOOL CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch( Msg )
{
case WM_INITDIALOG:
return TRUE;

case WM_COMMAND:
switch( wParam )
{
case IDOK:
MessageBox(NULL, "这是一个modal对话框的例子", "提示", MB_OK);
EndDialog(hwnd, 0);
return TRUE;
}
break;
}

return FALSE;
}
extern"C" __declspec(dllexport) void ShowDialog()
{
HINSTANCE hinst;
hinst=LoadLibrary("Modal_Dialog.dll"); //获取库所在的实例句柄
DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
FreeLibrary(hinst);
}
typedef void (*fp)();
HINSTANCE hDll;
fp Show;
hDll = LoadLibrary("Modal_Dialog.dll");
Show = (fp)GetProcAddress(hDll,"ShowDialog");
(*Show)();
FreeLibrary(hDll);

3、在Win32 Dll中创建modeless对话框

与modal对话框不同,modeless对话框的消息是要经过主程序消息循环的,这样一来,就必须在调用该Dll的主程序中处理对话框的消息循环,这就无法达到利用Dll来完成组件化开发的要求。其实我们可以人为的Modeless对话框创建一个窗口类,我们知道窗口过程是属于窗口类的,这样一来就有了主窗口的消息循环。

//name: Modeless_Dialog.cpp
#include <windows.h>
#include"resource.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);

extern"C" int __declspec(dllexport) ShowDialog()
{
static TCHAR szAppName[] = TEXT("Modeless_Dialog");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
HINSTANCE hInstance;
HWND hDialog;

hInstance = LoadLibrary("Modeless_Dialog.dll");

wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = DLGWINDOWEXTRA; // Note!
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(hInstance, szAppName);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
hwnd = CreateWindow(szAppName, TEXT("Modeless_Dialog"),
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);

// ShowWindow (hwnd, iCmdShow); //并不在这里显示主窗口
// UpdateWindow (hwnd);
hDialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), hwnd, DlgProc) ;

while ( GetMessage(&msg, NULL, 0, 0) )
{
if( hDialog == 0 || !IsDialogMessage(hDialog, &msg) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam ;

}
BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch( message )
{
case WM_INITDIALOG:
return true;
case WM_COMMAND:
switch( wParam )
{
case(IDOK):
MessageBox(NULL, "这是一个modeless对话框的例子", "提示", MB_OK);
DestroyWindow(hDlg);
PostQuitMessage(0);
return TRUE;
}
}
return FALSE;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

3、C/C++控制台程序隐藏窗口

  • 方法1
    在代码头文件下加上一句:
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址
#include<windows.h>
#pragma comment( linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )// 设置入口地址
int main()
{
MessageBox(NULL,"Hello","爱看书的小沐",NULL);
return 0;
}

注意:在编译器下运行时仍会出现黑框,但直接运行编译好的exe程序就不会显示黑框了。

  • 方法2:
    使用API函数隐藏自身窗口,但会有黑框快速闪过。
#include<windows.h>
int main()
{
HWND hwnd = NULL;
hwnd=FindWindow("ConsoleWindowClass",NULL);
if(hwnd){
ShowWindow(hwnd,SW_HIDE);
}
MessageBox(NULL,"Hello","爱看书的小沐",MB_OK);
system("pause");
return 0;
}
  • 方法3:
    写第二个程序,间接启动第一个程序,以窗口隐藏的方式。
#include<windows.h>
int main()
{
WinExec("MyTest.exe", SW_HIDE);
return 0;
}
  • 方法4:
    编写vbscript脚本:object.Run(strCommand, [intWindowStyle], [bWaitOnReturn])
Set objShell = CreateObject(Wscript.Shell) 
objShell.Run("MyTest.exe", 0, FALSE)
Set objShell = CreateObject(Wscript.Shell) 
objShell.Run notepad ,,true
objShell.Run
set wshshell = wscript.createobject("wscript.shell")
return = wshshell.run("notepad " & wscript.scriptfullname, 1, true)

run函数有三个参数:
第一个参数是你要执行的程序的路径。
第二个程序是窗口的形式,0是在后台运行;1表示正常运行;2表示激活程序并且显示为最小化;3表示激活程序并且显示为最大化;一共有10个这样的参数我只列出了4个最常用的。
第三个参数是表示这个脚本是等待还是继续执行,如果设为了true,脚本就会等待调用的程序退出后再向后执行。

其实,run做为函数,前面还有一个接受返回值的变量,一般来说如果返回为0,表示成功执行,如果不为0,则这个返回值就是错误代码,可以通过这个代码找出相应的错误。

后记

如果你觉得这些文字有一点点用处,可以给作者点个赞;╮( ̄▽ ̄)╭
如果你感觉作者写的不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O???
谢谢各位小伙伴们啦( ´ ▽ ‘)ノ ( ´ ▽ ` )っ!!!