#include <windows.h>
#define ID_LISTBOX 1
#define ID_TEXTBOX 2
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Environ") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW+1) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox ( NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("this is ENVIRON program"),
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
void FillListBox(HWND hwndList){
int iLength1;
TCHAR *pVarBlock,*pVarBeg,*pVarEnd,*pVarName,*pVarBlock1;
pVarBlock=pVarBlock1=GetEnvironmentStrings();
while(*pVarBlock){
if(*pVarBlock != '='){
pVarBeg=pVarBlock;
while(*pVarBlock++ != '=');
pVarEnd=pVarBlock-1;
iLength1=pVarEnd-pVarBeg;
pVarName=(TCHAR*)calloc(iLength1+1,sizeof(TCHAR));
CopyMemory(pVarName,pVarBeg,iLength1*sizeof(TCHAR));
pVarName[iLength1]='\0';
SendMessage(hwndList,LB_ADDSTRING,0,(LPARAM)pVarName);
free(pVarName);
}
while(*pVarBlock++ != '\0');
}
FreeEnvironmentStrings(pVarBlock1);
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
static HWND hwndList,hwndText;
int cxChar,cyChar;
int iLength,iIndex;
TCHAR *pVarName1,*pVar;
switch(message){
case WM_CREATE:
cxChar=LOWORD(GetDialogBaseUnits());
cyChar=HIWORD(GetDialogBaseUnits());
hwndList=CreateWindow(TEXT("listbox"),NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD,
cxChar,3*cyChar,16*cxChar,cyChar*10,hwnd,
(HMENU) ID_LISTBOX,(HINSTANCE) GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
hwndText=CreateWindow(TEXT("static"),NULL,WS_CHILD | WS_VISIBLE | SS_LEFT,
cxChar,cyChar,GetSystemMetrics(SM_CXSCREEN),cyChar,hwnd,
(HMENU) ID_TEXTBOX,(HINSTANCE) GetWindowLong(hwnd,GWL_HINSTANCE),NULL);
FillListBox(hwndList);
return 0;
case WM_SETFOCUS:
SetFocus(hwndList);
return 0;
case WM_COMMAND:
if(LOWORD(wParam)==ID_LISTBOX && HIWORD(wParam)==LBN_SELCHANGE){
iIndex=SendMessage(hwndList,LB_GETCURSEL,0,0);
iLength=SendMessage(hwndList,LB_GETTEXTLEN,iIndex,0)+1;
pVarName1=(TCHAR*) calloc(iLength,sizeof(TCHAR));
SendMessage(hwndList,LB_GETTEXT,iIndex,(LPARAM)pVarName1);
iLength=GetEnvironmentVariable(pVarName1,NULL,0);
pVar=(TCHAR*) calloc(iLength,sizeof(TCHAR));
GetEnvironmentVariable(pVarName1,pVar,iLength);
SetWindowText(hwndText,pVar);
free (pVarName1);
free (pVar);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
笔者按照书中的代码调试(F5)总是出现
“ Windows 已在 ENVIRON1.exe 中触发一个断点。其原因可能是堆被损坏,这说明 ENVIRON1.exe 中或它所加载的任何 DLL 中有 Bug。。”
这个应该内存释放出现了问题,检查发现书中代码在
FreeEnvironmentStrings(pVarBlock);
有问题,因为pVarBlock在
while(*pVarBlock++ != '=');
while(*pVarBlock++ != '\0');
值已经改变了,不能利用该指针进行内存释放,本文中利用pVarBlock1进行内存的释放。
另注:
运行本程序时,总是出现“LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏”这个问题,网上已有解决方案:项目\属性\配置属性\清单工具\输入和输出\嵌入清单:原来是“是”,改成“否”。不过每次创建新项目总是要重新设置一遍。