文号
821608
阅读
5774
回复
1
收藏
1
VC++实用Win32模板:空程序和一个按钮两个文本框的对话框程序
2016/06/17
IP:四川

虽然C#更好用,但是有时候想用WinAPI却不知道它的特性是什么,或者是想查找一下WinAPI相关结构和常量的定义,这时还是要用到VC++。

使用WinAPI最好还是在GUI程序中进行,DOS窗口和WinAPI交互要考虑的东西太多,显示效果也太差(经常出现问号方框之类的)。

一般来说,最简单GUI程序就是只有WinMain的程序了,新建一个空Win32工程(不要默认,否则它会新建一个非常复杂的示例程序,还会开启预编译头文件):

w32.png

然后在工程里面添加一个CPP文件,按照下面的程序写即可:

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
    // 在这里写程序
    MessageBox(NULL, L"我要退出", L"消息", MB_OK);
    return 0;
}
</windows.h>

也可以命令行编译:

cl w32.cpp kernel32.lib user32.lib

这种程序与用户交互一般只有使用MessageBox,有时候不够用,我们就要新建一个自定义对话框,下面的程序模板包含一个按钮和两个对话框,还包括文本的I/O支持。

txtdlg.png

除了这个模板以外,如果你是在使用Community或商业版,还可以有其它的方便的途径,比如选择新建一个MFC对话框程序,然后拖一个按钮两个文本框,设置好属性以后双击文本框写程序就OK了。

RC文件(资源脚本,可以自己用VC++资源编辑器生成):

#include <windows.h>

#define IDD_DIALOG1                     101
#define IDC_BUTTON1                     1001
#define IDC_EDIT1                       1002
#define IDC_EDIT2                       1003

IDD_DIALOG1 DIALOGEX 0, 0, 221, 137
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    PUSHBUTTON      "Button1",IDC_BUTTON1,7,7,50,14
    EDITTEXT        IDC_EDIT1,7,28,99,102,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
    EDITTEXT        IDC_EDIT2,114,28,100,102,ES_MULTILINE | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL
END
</windows.h>

CPP文件(源代码文件):

#ifndef UNICODE
#define UNICODE
#endif

#include <windows.h>
#include <commctrl.h>

// 如果包含了resource.h就不用手动指定资源序号了
//#include "resource.h"
#define IDD_DIALOG1                     101
#define IDC_BUTTON1                     1001
#define IDC_EDIT1                       1002
#define IDC_EDIT2                       1003

HINSTANCE hMainInst;

TCHAR *input; // 自动保存的输入字符串
int inputlen; // 输入字符串的长度

// 输出字符串的函数
void OutputText(HWND hdlg, TCHAR *str)
{
	SendDlgItemMessage(hdlg, IDC_EDIT2, EM_SETSEL, -1, -1);
	SendDlgItemMessage(hdlg, IDC_EDIT2, EM_REPLACESEL, 0, (LPARAM)str);
}

void OnButton1(HWND hdlg)
{
	// TODO: 程序逻辑
	OutputText(hdlg, L"我是输出的字符串\r\n");
	OutputText(hdlg, input);
	OutputText(hdlg, L"\r\n");
	return;
}

BOOL CALLBACK DlgProc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		break;
	case WM_CLOSE:
		EndDialog(hdlg, 0);
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDC_BUTTON1:
			inputlen = (int)SendDlgItemMessage(hdlg, IDC_EDIT1, WM_GETTEXTLENGTH, 0, 0);
			input = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (inputlen + 1) * sizeof(TCHAR));
			GetDlgItemText(hdlg, IDC_EDIT1, input, inputlen + 1);
			OnButton1(hdlg);
			HeapFree(GetProcessHeap(), 0, input);
			return TRUE;
		}
		break;
	}
	return FALSE;
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
	hMainInst = hInst;
	return (int)DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)DlgProc);
}
</commctrl.h></windows.h>

命令行编译:

rc mydlg1.rc
cl mydlg1.cpp mydlg1.res kernel32.lib user32.lib
[ 修改于10年6个月前 - 2016/06/17 18:05:28 ]
acmilan作者
10年6个月前修改于 10年6个月前IP:四川
821870
1楼

如果是C#程序的话,也可以用这种方法移植控制台程序

StringReader cin = new StringReader(textBox1.Text);
StringWriter cout = new StringWriter();

// 将Console.Read(Line)替换为cin.Read(Line)
// 将Console.Write(Line)替换为cout.Write(Line)
cout.WriteLine(cin.ReadLine());

textBox2.Text += cout.ToString();

更方便的做法,把cout直接命名为Console,这样只需要改Read/ReadLine的前缀就行了:

StringReader cin = new StringReader(textBox1.Text);
StringWriter Console = new StringWriter();

// 将Console.Read(Line)替换为cin.Read(Line)
Console.WriteLine(cin.ReadLine());

textBox2.Text += Console.ToString();

如果需要实时更新输出的话,需要新建一个线程并使用Invoke进行更新,此处不再作介绍,感兴趣的同学可以自己研究一下。

引用
评论
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的