即将两年的.NET经验,一年的BMC经验,作为一个电子专业的人来说,心中仍然保留着对C和C++的情结。

最近项目空闲之余在看Windows Programming和Windows via C/C++,并且用C++为我们开发的类库制作安装程序,虽然只是简单的Windows C程序,但是那份成就感油然而生。本文记录开发这个小程序过程中的心得:

1、基于对话框的windows程序

虽然说标准的Windows程序总是由用户注册的窗口类开始的,并且程序员需要自己用while来接收应用程序消息队列里的消息,并处理。但是如果想要快速开发小程序的话,可以像下面这样基于对话框的来开始程序。对话框自动建立消息循环,接收消息,我们要做的只是定义一个对话框处理函数。

int WINAPI _tWinMain(
	HINSTANCE hInstance,
	HINSTANCE,
	PTSTR szCmdLine,
	int iCmdShow)
{
	DialogBox(hInstance...,DlgProc);
	return 0;
}

 

2、检查内存泄漏

虽说是个小程序,但是在最后执行的时候,程序返回后,windows弹出应用程序出现错误。我猜想是内存泄漏了。实在惭愧,这么一个小程序都能搞出内存泄漏。后来在网上查到一个检查内存泄漏的方法:http://www.cppblog.com/Lyt/archive/2009/03/22/77517.html

#define _CRTDBG_MAP_ALLOC

#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h>


int WINAPI _tWinMain(
	HINSTANCE hInstance,
	HINSTANCE,
	PTSTR szCmdLine,
	int iCmdShow)
{
	hInstance = hInstance;
	...
	_CrtDumpMemoryLeaks();
	return 0;
}

这里的_CrtDumpMemoryLeaks()会在vs的Output窗口中给出内存泄漏的报告。

 

3、根据对话框句柄无法获取对话框的资源ID

虽说GetWindowLong (hwndChild, GWL_ID) ;是通过句柄得到窗口资源ID,但是当句柄是对话框句柄是是无效的。另外相关函数如下:

id = GetDlgCtrlID (hwndChild);

hwndChild = GetDlgItem(hwndParent, id); 

 

4、GetWindowRect(hDlg,&rect);返回窗口的大小,返回的rect中的right和bottom竟然是窗口的width和height,真不知道为什么取名字要那么歧义。。GetSystemMetrics(SM_CXFULLSCREEN)和GetSystemMetrics(SM_CYFULLSCREEN)获得显示屏的像素信息。

MoveWindow(hDlg,inewLeft,inewTop,width,height,FALSE);可以设置窗口的位置。

 

5、设置checkbox:

SendMessage(hwnd, BM_SETCHECK, BST_CHECKED, 0);
SendMessage(hwnd, BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(hwnd, BM_GETCHECK, 0, 0));

 

6、FindFirstFile的目标文件可以有通配符,但是必须是全路径。还可用来判断路径是否存在(FILE_ATTRIBUTE_DIRECTORY)

WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(tmp,&FindFileData);
if(INVALID_HANDLE_VALUE == hFind){

}
else{
	FindClose(hFind);
}

 

7、字符串处理

_tcscpy、_tcscat、_tcslen、_tcscmp、_tcsstr

 

8、注册表操作,如果要设置环境变量,必须直接在注册表中设置

RegOpenKeyEx(HKEY_LOCAL_MACHINE
				,TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\")
				,0
				,KEY_ALL_ACCESS
				,&hEnvKEY)


//读取键值的时候可以先读一次,获取需要的缓冲区长度和数据类型
RegQueryValueEx(hEnvKEY,TEXT("Path"),NULL,&dwType,NULL,&cbData)
RegQueryValueEx(hEnvKEY,TEXT("Path"),NULL,&dwType,lpbOrignalEnvPath,&cbData);

//返回的LPBYTE其实已经是字符数组了,直接强转就可以了
TCHAR* szOrignalEnvPath = (TCHAR*)lpbOrignalEnvPath;

#ifdef _UNICODE,UNICODE
				LSTATUS status = RegSetValueEx(hEnvKEY,TEXT("Path"),NULL,dwType,(LPBYTE)szTargetEnvPath,_tcslen(szTargetEnvPath)*2+2);
#else
				LSTATUS status = RegSetValueEx(hEnvKEY,TEXT("Path"),NULL,dwType,(LPBYTE)szTargetEnvPath,_tcslen(szTargetEnvPath)+1);

//设置完后可以通过下面方法,通知系统进程,环境变量变化了。这也提示我们在编写应用程序的时候有时需要处理WM_SETTINGCHANGE的意义
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)TEXT("Environment"));

9、获取系统变量和环境变量

//同样可以通过调用两次来获取缓冲区长度
dwSize = GetEnvironmentVariable(TEXT("HOMEDRIVE"),NULL,0);
szHomeDrive = new TCHAR[dwSize+1];
GetEnvironmentVariable(TEXT("HOMEDRIVE"),szHomeDrive,dwSize+1);

10、C多文件编译、作用域和存储周期

 http://www.cnblogs.com/P_Chou/archive/2012/05/25/2518097.html