 [原创]教你怎么写出单线程多窗口程序(有实例演示)——兼无情嘲笑万邦来朝的荒谬言论 [博客帖]
文章提交者:fifa007
加贴在 国货当自强
铁血论坛 http://bbs.tiexue.net/bbs_155.html
以万邦来朝的能力,他大约以为做一个单线程多窗口的程序很困难。我本来看战友迎战了,不想搭理他,没想到他却蹬鼻子上脸。正好,我就再写一篇教程,手把手教大家如何做出一个单线程多窗口程序来。
先声明,我这个程序的主窗口叫做“万邦吹牛,牛皮无敌”,这个主窗口代表论坛里面的万邦,那么我的程序设定的可以生成10个子窗口(其实多少无所谓,只要你的电脑能跑得动就行),子窗口代表万邦在论坛中的马甲,分别编为1,2,3...,10。是不是很贴近现实啊?就是么,万邦自己的主ID加上一系列的马甲,其实都只有他一个人在操作,等于说,其实就只是单线程而已,不过用了N个马甲(开了N个窗口),看起来人多势众了。
[ 转自铁血社区 http://bbs.tiexue.net/ ] 这个是程序的运行效果,可打开10个子窗口。鼠标点击在每个子窗口时,这些子窗口还能自报家门,报告大家他是几号马甲;看见没,除了那个大窗口,还有10个小的依次排开的窗口
可执行文件放在了我的G宝盘上,可下载,才88K(我的杀毒软件:卡巴个人版6.0病毒库2007-10-26。所以请放心),地址:http://c4debug.gbaopan.com/files/ec8b7fe6fa19424b977ce07065e4a7be.gbp
这个是用SPY查看线程和窗口,可以很清楚的看到只有1个线程,但是却有N多窗口
以下是我的源代码:
[ 转自铁血社区 http://bbs.tiexue.net/ ]
// test.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "test.h"
#include "stdio.h"
#define MAX_LOADSTRING 100
[ 转自铁血社区 http://bbs.tiexue.net/ ]
#define ID_BUTTON1 0x8801
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
TCHAR sbTitle[MAX_LOADSTRING]="万邦来朝马甲"; // 标题栏文本——马甲窗口标题栏
[ 转自铁血社区 http://bbs.tiexue.net/ ] TCHAR sbWindowClass[MAX_LOADSTRING]; // 子窗口类名——马甲窗口
int cmdshow;
int mjNUM = 0; //万邦来朝马甲窗口计数
HWND wanbangMJ[10]; //支持生成10个万邦来朝马甲
HWND wanbangMJSC[10]; //支持生成10个万邦来朝马甲的按钮
int wanbangMJSCID[10]; //10个万邦来朝马甲的按钮ID
[ 转自铁血社区 http://bbs.tiexue.net/ ]
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
HWND DisplayWanBangMJ(HWND hWnd , HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
[ 转自铁血社区 http://bbs.tiexue.net/ ]
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: 在此放置代码。
[ 转自铁血社区 http://bbs.tiexue.net/ ] MSG msg;
HACCEL hAccelTable;
cmdshow = nCmdShow;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST, szWindowClass, MAX_LOADSTRING);
[ 转自铁血社区 http://bbs.tiexue.net/ ] MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
[ 转自铁血社区 http://bbs.tiexue.net/ ]
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TEST);
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
[ 转自铁血社区 http://bbs.tiexue.net/ ] TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
[ 转自铁血社区 http://bbs.tiexue.net/ ]
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
// 注释:
[ 转自铁血社区 http://bbs.tiexue.net/ ] //
// 仅当希望在已添加到 Windows 95 的
// “RegisterClassEx”函数之前此代码与 Win32 系统兼容时,
// 才需要此函数及其用法。调用此函数
// 十分重要,这样应用程序就可以获得关联的
// “格式正确的”小图标。
[ 转自铁血社区 http://bbs.tiexue.net/ ] //
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
[ 转自铁血社区 http://bbs.tiexue.net/ ] wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TEST);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
[ 转自铁血社区 http://bbs.tiexue.net/ ] wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;//(LPCTSTR)IDC_TEST;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
[ 转自铁血社区 http://bbs.tiexue.net/ ]
//
// 函数: InitInstance(HANDLE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
[ 转自铁血社区 http://bbs.tiexue.net/ ] //
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
[ 转自铁血社区 http://bbs.tiexue.net/ ] HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
[ 转自铁血社区 http://bbs.tiexue.net/ ] return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
[ 转自铁血社区 http://bbs.tiexue.net/ ] //
// 创建和显示万邦来朝马甲窗口
//
HWND DisplayWanBangMJ(HWND hWnd , HINSTANCE hInstance)
{
HWND hwnd;
[ 转自铁血社区 http://bbs.tiexue.net/ ] char buf[100];
if(mjNUM > 9)
{
MessageBox(NULL,"做人不能太贪心,10个马甲还不够?","万邦马甲制造机",MB_OK);
return NULL;
}
[ 转自铁血社区 http://bbs.tiexue.net/ ]
sprintf(buf , "%s%.2d号",sbTitle,mjNUM+1);
hInst = hInstance; // 将实例句柄存储在全局变量中
hwnd = CreateWindow(szWindowClass, buf, WS_OVERLAPPEDWINDOW,
mjNUM*100, mjNUM*50,400, 100, hWnd, NULL, hInstance, NULL);
if (!hwnd)
{
[ 转自铁血社区 http://bbs.tiexue.net/ ] return NULL;
}
ShowWindow(hwnd, 1);//cmdshow);
UpdateWindow(hwnd);
return hwnd;
}
[ 转自铁血社区 http://bbs.tiexue.net/ ] //
// 函数: WndProc(HWND, unsigned, WORD, LONG)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
[ 转自铁血社区 http://bbs.tiexue.net/ ] // WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
[ 转自铁血社区 http://bbs.tiexue.net/ ] int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static HWND activeWnd;
static int buttonID;
switch (message)
[ 转自铁血社区 http://bbs.tiexue.net/ ] {
case WM_CREATE:
wanbangMJSC[mjNUM] = CreateWindow("BUTTON","制造万邦马甲",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
0, 0, 100, 30, hWnd, (HMENU)ID_BUTTON1 ,(HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
wanbangMJSCID[mjNUM] = GetDlgCtrlID(wanbangMJSC[mjNUM]);
break;
[ 转自铁血社区 http://bbs.tiexue.net/ ]
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
if(wmEvent == BN_CLICKED)
{
if(wmId == wanbangMJSCID[0] || wmId == wanbangMJSCID[1] || wmId == wanbangMJSCID[2] || wmId == wanbangMJSCID[3] ||
[ 转自铁血社区 http://bbs.tiexue.net/ ] wmId == wanbangMJSCID[4] || wmId == wanbangMJSCID[5] || wmId == wanbangMJSCID[6] || wmId == wanbangMJSCID[7] ||
wmId == wanbangMJSCID[8] || wmId == wanbangMJSCID[9])
{
if(mjNUM > 9)
{
MessageBox(NULL,"做人不能太贪心,10个马甲还不够?","万邦马甲制造机",MB_OK);
[ 转自铁血社区 http://bbs.tiexue.net/ ] return NULL;
}
else
wanbangMJ[mjNUM++] = DisplayWanBangMJ(hWnd , (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE));
}
}
[ 转自铁血社区 http://bbs.tiexue.net/ ] switch (wmId)
{
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
[ 转自铁血社区 http://bbs.tiexue.net/ ] case WM_LBUTTONDOWN:
//activeMOD = LOWORD(wParam);
activeWnd = GetTopWindow(hWnd);//(HWND)(lParam);
if(mjNUM)
{
HDC hdc;
[ 转自铁血社区 http://bbs.tiexue.net/ ] hdc = GetDC(activeWnd);
if(activeWnd == wanbangMJSC[0])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第1号马甲","撒谎机器",MB_OK);
}
else if(activeWnd == wanbangMJSC[1])
[ 转自铁血社区 http://bbs.tiexue.net/ ] {
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第2号马甲","撒谎机器",MB_OK);
}
else if(activeWnd == wanbangMJSC[2])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第3号马甲","撒谎机器",MB_OK);
[ 转自铁血社区 http://bbs.tiexue.net/ ] }
else if(activeWnd == wanbangMJSC[3])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第4号马甲","撒谎机器",MB_OK);
}
else if(activeWnd == wanbangMJSC[4])
[ 转自铁血社区 http://bbs.tiexue.net/ ] {
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第5号马甲","撒谎机器",MB_OK);
}
else if(activeWnd == wanbangMJSC[5])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第6号马甲","撒谎机器",MB_OK);
[ 转自铁血社区 http://bbs.tiexue.net/ ] }
else if(activeWnd == wanbangMJSC[6])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第7号马甲","撒谎机器",MB_OK);
}
else if(activeWnd == wanbangMJSC[7])
[ 转自铁血社区 http://bbs.tiexue.net/ ] {
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第8号马甲","撒谎机器",MB_OK);
}
else if(activeWnd == wanbangMJSC[8])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第9号马甲","撒谎机器",MB_OK);
[ 转自铁血社区 http://bbs.tiexue.net/ ] }
else if(activeWnd == wanbangMJSC[9])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第10号马甲","撒谎机器",MB_OK);
}
else
[ 转自铁血社区 http://bbs.tiexue.net/ ] {
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎主窗口","撒谎机器",MB_OK);
}
}
break;
case WM_PAINT:
[ 转自铁血社区 http://bbs.tiexue.net/ ] hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
[ 转自铁血社区 http://bbs.tiexue.net/ ] break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
[ 转自铁血社区 http://bbs.tiexue.net/ ]
其实,最关键的实现多窗口的功能代码只有几段,这几段才是我自己手动写出来的,其他的都是VC自动生成的:
这个是生成子窗口的代码
HWND DisplayWanBangMJ(HWND hWnd , HINSTANCE hInstance)
{
HWND hwnd;
char buf[100];
[ 转自铁血社区 http://bbs.tiexue.net/ ] if(mjNUM > 9)
{
MessageBox(NULL,"做人不能太贪心,10个马甲还不够?","万邦马甲制造机",MB_OK);
return NULL;
}
sprintf(buf , "%s%.2d号",sbTitle,mjNUM+1);
[ 转自铁血社区 http://bbs.tiexue.net/ ]
hInst = hInstance; // 将实例句柄存储在全局变量中
hwnd = CreateWindow(szWindowClass, buf, WS_OVERLAPPEDWINDOW,
mjNUM*100, mjNUM*50,400, 100, hWnd, NULL, hInstance, NULL);
if (!hwnd)
{
return NULL;
[ 转自铁血社区 http://bbs.tiexue.net/ ] }
ShowWindow(hwnd, 1);//cmdshow);
UpdateWindow(hwnd);
return hwnd;
}
|
[ 转自铁血社区 http://bbs.tiexue.net/ ] 这个是生成子窗口的代码
生成产生子窗口的按钮
case WM_CREATE:
wanbangMJSC[mjNUM] = CreateWindow("BUTTON","制造万邦马甲",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
0, 0, 100, 30, hWnd, (HMENU)ID_BUTTON1 ,(HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
wanbangMJSCID[mjNUM] = GetDlgCtrlID(wanbangMJSC[mjNUM]);
[ 转自铁血社区 http://bbs.tiexue.net/ ] |
这个是生成产生子窗口的按钮
对按钮事件进行反应的代码
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
[ 转自铁血社区 http://bbs.tiexue.net/ ] if(wmEvent == BN_CLICKED)
{
if(wmId == wanbangMJSCID[0] || wmId == wanbangMJSCID[1] || wmId == wanbangMJSCID[2] || wmId == wanbangMJSCID[3] ||
wmId == wanbangMJSCID[4] || wmId == wanbangMJSCID[5] || wmId == wanbangMJSCID[6] || wmId == wanbangMJSCID[7] ||
wmId == wanbangMJSCID[8] || wmId == wanbangMJSCID[9])
{
[ 转自铁血社区 http://bbs.tiexue.net/ ] if(mjNUM > 9)
{
MessageBox(NULL,"做人不能太贪心,10个马甲还不够?","万邦马甲制造机",MB_OK);
return NULL;
}
else
[ 转自铁血社区 http://bbs.tiexue.net/ ] wanbangMJ[mjNUM++] = DisplayWanBangMJ(hWnd , (HINSTANCE) GetWindowLong(hWnd, GWL_HINSTANCE));
}
}
|
这一段是对按钮事件进行反应的代码,也就是说,一按按钮,就执行这一段
鼠标点击
[ 转自铁血社区 http://bbs.tiexue.net/ ] case WM_LBUTTONDOWN:
//activeMOD = LOWORD(wParam);
activeWnd = GetTopWindow(hWnd);//(HWND)(lParam);
if(mjNUM)
{
HDC hdc;
[ 转自铁血社区 http://bbs.tiexue.net/ ] hdc = GetDC(activeWnd);
if(activeWnd == wanbangMJSC[0])
{
MessageBox(activeWnd,"欢迎前来观看万邦来朝的撒谎表演,我是万邦撒谎第1号马甲","撒谎机器",MB_OK);
}
|
[ 转自铁血社区 http://bbs.tiexue.net/ ] 另外,我加了点小小娱乐功能,就是鼠标点击在哪个窗口上,哪个窗口就会弹出一个对话框来自报家门。 本文内容于 2007-10-27 18:31:43 被fifa007编辑 转载请注明出自铁血tiexue.net, 本贴地址: http://bbs.tiexue.net/post_2337889_1.html [点击查看灌水过滤后的回复]
本帖已赚工分: 510
本帖已赚金币: 0
编辑: fifa007 10-27 18:28
编辑: fifa007 10-27 18:30
加准原创: wsj1723 10-28 20:51
原创转正: 鹰的重生 10-30 00:49
---------------------------------------------- [img=200x200]http://pic.tiexue.net/pic.aspx?id=33506[/img]
吴门之子,季扎之后;
生于潇湘风雨之畔,
长于荆楚蜀汉之中;
素喜辞赋,有金戈铁马之气;
与人为善,但求天地人和;
喜家国之喜,忧天下之忧。
此志甲申年丁丑月乙未日。
|