输入Big5字符,返回Gb简体字符 //————————————————————————— //函数输入Big5字符,返回Gb简体字符 //————————————————————————— AnsiString __fastcall Big2Gb(AnsiString sBig) { char pszBig5=NULL; //Big5编码的字符 wchar_t wszUnicode=NULL; //Unicode编码的字符 char pszGbt=NULL; //Gb编码的繁体字符 char pszGbs=NULL; //Gb编码的简体字符 AnsiString sGb; //返回的字符串 int iLen=0; //需要转换的字符数
pszBig5=sBig.c_str(); //读入需要转换的字符参数
//计算转换的字符数 iLen=MultiByteToWideChar (950, 0, pszBig5, -1, NULL,0) ; //给wszUnicode分配内存 wszUnicode=new wchar_t[iLen+1]; //转换Big5码到Unicode码,使用了API函数MultiByteToWideChar MultiByteToWideChar (950, 0, pszBig5, -1, wszUnicode,iLen);
//计算转换的字符数 iLen=WideCharToMultiByte (936, 0, (PWSTR) wszUnicode, -1, NULL,0, NULL, NULL) ; //给pszGbt分配内存 pszGbt=new char[iLen+1]; //给pszGbs分配内存 pszGbs=new char[iLen+1]; //转换Unicode码到Gb码繁体,使用API函数WideCharToMultiByte WideCharToMultiByte (936, 0, (PWSTR) wszUnicode, -1, pszGbt,iLen, NULL, NULL) ;
//转换Gb码繁体到Gb码简体,使用API函数LCMapString LCMapString(0x0804,LCMAP_SIMPLIFIED_CHINESE, pszGbt, -1, pszGbs, iLen);
//返回Gb码简体字符 sGb=pszGbs;
//释放内存 delete [] wszUnicode; delete [] pszGbt; delete [] pszGbs;
return sGb; }
输入Gb字符,返回Big5字符 //————————————————————————— //函数输入Gb字符,返回Big5字符 //————————————————————————— AnsiString __fastcall Gb2Big(AnsiString sGb) { char pszGbt=NULL; //Gb编码的繁体字符 char pszGbs=NULL; //Gb编码的简体字符 wchar_t wszUnicode=NULL; //Unicode编码的字符 char pszBig5=NULL; //Big5编码的字符 AnsiString sBig5; //返回的字符串 int iLen=0; //需要转换的字符数
pszGbs=sGb.c_str(); //读入需要转换的字符参数
//计算转换的字符数 iLen=MultiByteToWideChar (936, 0, pszGbs, -1, NULL,0) ;
//给pszGbt分配内存 pszGbt=new char[iLen2+1]; //转换Gb码简体到Gb码繁体,使用API函数LCMapString LCMapString(0x0804,LCMAP_TRADITIONAL_CHINESE, pszGbs, -1, pszGbt, iLen2);
//给wszUnicode分配内存 wszUnicode=new wchar_t[iLen+1]; //转换Gb码到Unicode码,使用了API函数MultiByteToWideChar MultiByteToWideChar (936, 0, pszGbt, -1, wszUnicode,iLen);
//计算转换的字符数 iLen=WideCharToMultiByte (950, 0, (PWSTR) wszUnicode, -1, NULL,0, NULL, NULL) ; //给pszBig5分配内存 pszBig5=new char[iLen+1]; //转换Unicode码到Big5码,使用API函数WideCharToMultiByte WideCharToMultiByte (950, 0, (PWSTR) wszUnicode, -1, pszBig5,iLen, NULL, NULL) ;
//返回Big5码字符 sBig5=pszBig5;
//释放内存 delete [] wszUnicode; delete [] pszGbt; delete [] pszBig5;
return sBig5; }
动态加载位图
void CCreateRandomBMPDlg::OnBtnTest() { // TODO: Add your control notification handler code here HBITMAP hBmp;
CFileDialog dlg(TRUE, "bmp", NULL, 0, "位图文件 (*.bmp)|*.bmp||", this);
if (dlg.DoModal() != IDOK)
{
return;
}
hBmp = (HBITMAP) LoadImage(NULL, dlg.GetPathName(), IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if (hBmp == NULL)
{
return;
}
BITMAP bm;
PBITMAPINFO bmpInf;
if (GetObject(hBmp, sizeof(bm), &bm;) == 0)
return ;
int nPaletteSize = 0;
if (bm.bmBitsPixel < 16)
nPaletteSize = (int) pow(2, bm.bmBitsPixel);
bmpInf = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * nPaletteSize);
//-----------------------------------------------
bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInf->bmiHeader.biWidth = bm.bmWidth;
bmpInf->bmiHeader.biHeight = bm.bmHeight;
bmpInf->bmiHeader.biPlanes = bm.bmPlanes;
bmpInf->bmiHeader.biBitCount = bm.bmBitsPixel;
bmpInf->bmiHeader.biCompression = BI_RGB;
bmpInf->bmiHeader.biSizeImage = (bm.bmWidth + 7) /
8 * bm.bmHeight * bm.bmBitsPixel;
bmpInf->bmiHeader.biXPelsPerMeter = 0;
bmpInf->bmiHeader.biYPelsPerMeter = 0;
bmpInf->bmiHeader.biClrUsed = 0;
bmpInf->bmiHeader.biClrImportant = 0;
//-----------------------------------------------
HDC hDC = ::GetWindowDC(NULL);
if (!::GetDIBits(hDC, hBmp, 0, (WORD) bm.bmHeight, NULL, bmpInf,
DIB_RGB_COLORS))
{
LocalFree(bmpInf);
::ReleaseDC(NULL, hDC);
return ;
}
void* buf = (void*) new char[bmpInf->bmiHeader.biSizeImage];
if (buf == NULL)
{
::ReleaseDC(NULL, hDC);
LocalFree(bmpInf);
return ;
}
if (!::GetDIBits(hDC, hBmp, 0, (UINT) bm.bmHeight, buf, bmpInf,
DIB_RGB_COLORS))
{
::ReleaseDC(NULL, hDC);
delete[]buf;
LocalFree(bmpInf);
return ;
}
::ReleaseDC(NULL, hDC);
CString sMsg;
sMsg.Format("BitsPixel:%d,width:%d,height:%d", bm.bmBitsPixel, bm.bmWidth,
bm.bmHeight);
AfxMessageBox(sMsg);
CClientDC dc(this);
if (bm.bmBitsPixel == 8)
{
BYTE* pData = (BYTE*) buf;
int nWidth = bm.bmWidth;
while (nWidth % 4 != 0)
{
//Bmp每行数据都是4个字节的整数倍。
nWidth++;
}
for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
RGBQUAD rgbQ;
rgbQ = bmpInf->bmiColors[pData[i * nWidth + j]];
dc.SetPixel(j, bm.bmHeight - i,
RGB(rgbQ.rgbRed, rgbQ.rgbGreen, rgbQ.rgbBlue));
}
}
}
else if (bm.bmBitsPixel == 16)
{
BYTE* pData = (BYTE*) buf;
int nWidth = bm.bmWidth*2;
while (nWidth % 4 != 0)
{
nWidth++;
}
BYTE red, green, blue;
for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
blue = pData[i * nWidth + j * 2] & 0x1F;
green = pData[i * nWidth + j * 2] >> 5;
green |= (pData[i * nWidth + j * 2 + 1] & 0x03) << 3;
red = (pData[i * nWidth + j * 2 + 1] >> 2) & 0x1F;
WORD wRed = red*8;
WORD wBlue = blue*8;
WORD wGreen = green*8;
red = min(255, wRed);
blue = min(255, wBlue);
green = min(255, wGreen);
dc.SetPixel(j, bm.bmHeight - i, RGB(red, green, blue));
}
}
}
else if (bm.bmBitsPixel == 24)
{
BYTE* pData = (BYTE*) buf;
int nWidth = bm.bmWidth*3;
while (nWidth % 4 != 0)
{
nWidth++;
}
for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
dc.SetPixel(j, bm.bmHeight -
i,
RGB(pData[i * nWidth + j * 3 + 2],
pData[i * nWidth + j * 3 + 1],
pData[i * nWidth + j * 3]));
}
}
}
else if (bm.bmBitsPixel == 32)
{
BYTE* pData = (BYTE*) buf;
int nWidth = bm.bmWidth*4;
for (int i = 0; i < bm.bmHeight; i++)
{
for (int j = 0; j < bm.bmWidth; j++)
{
dc.SetPixel(j, bm.bmHeight -
i,
RGB(pData[i * nWidth + j * 4 + 2],
pData[i * nWidth + j * 4 + 1],
pData[i * nWidth + j * 4]));
}
}
}
delete[]buf;
DeleteObject(hBmp);
LocalFree(bmpInf);
}
ADO连接SQL的一般过程
void ADOConn::OnInitADOConn() { ::CoInitialize(NULL); // 初始化OLE/COM库环境 ,为访问ADO接口做准备
try { // 创建Connection对象 m_pConnection.CreateInstance(“ADODB.Connection”); // 设置连接字符串,必须是BSTR型或者_bstr_t类型 _bstr_t strConnect = “Provider=SQLOLEDB; Server=flyspider;Database=HrSys; uid=sa; pwd=;”; m_pConnection->Open(strConnect,””,””,adModeUnknown); } // 捕捉异常 catch(_com_error e) { // 显示错误信息 AfxMessageBox(e.Description()); } }
// 执行查询 _RecordsetPtr& ADOConn::GetRecordSet(_bstr_t bstrSQL) { try { // 连接数据库,如果Connection对象为空,则重新连接数据库 if(m_pConnection==NULL) OnInitADOConn(); // 创建记录集对象 m_pRecordset.CreateInstance(__uuidof(Recordset)); // 取得表中的记录 m_pRecordset->Open(bstrSQL,m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText); } // 捕捉异常 catch(_com_error e) { // 显示错误信息 AfxMessageBox(e.Description()); } // 返回记录集 return m_pRecordset; }
// 执行SQL语句,Insert Update _variant_t BOOL ADOConn::ExecuteSQL(_bstr_t bstrSQL) { //_variant_t RecordsAffected; try { // 是否已经连接数据库 if(m_pConnection == NULL) OnInitADOConn(); // Connection对象的Execute方法:(_bstr_t CommandText, // VARIANT * RecordsAffected, long Options ) // 其中CommandText是命令字串,通常是SQL命令。 // 参数RecordsAffected是操作完成后所影响的行数, // 参数Options表示CommandText的类型:adCmdText-文本命令;adCmdTable-表名 // adCmdProc-存储过程;adCmdUnknown-未知 m_pConnection->Execute(bstrSQL,NULL,adCmdText); return true; } catch(_com_error e) { AfxMessageBox(e.Description()); return false; } }
void ADOConn::ExitConnect() { // 关闭记录集和连接 if (m_pRecordset != NULL) m_pRecordset->Close(); m_pConnection->Close(); // 释放环境 ::CoUninitialize(); }
截获系统注销时候的消息
使用WH_CALLWNDPROC类型钩子,回调函数如下:
LRESULT CALLBACK MyProc(int code, WPARAM wParam, LPARAM lParam) { switch (((CWPSTRUCT)lParam)->message) { case WM_QUERYENDSESSION: { switch( ((CWPSTRUCT)lParam)->lParam ) { case ENDSESSION_LOGOFF: { FILE pFile = NULL; ((CWPSTRUCT)lParam)->message = 0; AfxMessageBox(TEXT(“log off”)); return 0; } break; } } } return ::CallNextHookEx(g_hMessage, code, wParam, lParam); }
判断是否为文件夹或者文件
1 | int IsDirectoryOrFile(CString strFileName) |
Windows 任务管理器如何确定应用程序没有响应
最近参加的一个项目要求实现远程任务管理功能,也就是”Remote Task Manager”(RTM)。我把它与Windows NT的任务管理器进行了比较,发现标准的任务管理器显示应用程序的状态(正在运行或者没有响应)。标准的任务管理器发送(通过SendMessageTimeout函数)一个消息到主应用窗口,如果函数调用失败或者超时–则应用程序的状态就是”没有响应”,否则状态为”正在运行”。 但我发现还有一个更好的解决方法。本文将通过实例程序进行示范。这个方法的思路是通过调用User32.dll中一个未公开的函数来实现的。这个函数存在于Windows 9x和Windows NT/2000系统中,但在两个系统中的名字是不同的。Windows 9x系统中的名字为:IsHungThread,在Windows NT/2000系统中的名字为IsHungAppWindow。下面是它们的原型:
1 | BOOL IsHungAppWindow ( |
不幸的是,微软在User32.lib中没有提供这两个函数的输出。也就是说,这两个函数是未公开函数,如果要在程序中使用它们,则必须通过GetProcAddress和GetModuleHandle函数动态加载:
1 | typedef BOOL (WINAPI *PROCISHUNGAPPWINDOW) (HWND); |
利用未公布API获取CPU使用率
利用ntdll.dll中没有公开的API函数: NtQuerySystemInformation
typedef LONG (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG); PROCNTQSI NtQuerySystemInformation;
NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
GetModuleHandle("ntdll"),
"NtQuerySystemInformation"
);
if (!NtQuerySystemInformation)
{ return; }
// get number of processors in the system
status = NtQuerySystemInformation(SystemBasicInformation,
&SysBaseInfo;,sizeof(SysBaseInfo),NULL);
if (status != NO_ERROR)
{ return; } status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo;,sizeof(SysTimeInfo),0); if (status!=NO_ERROR) { return; } // get new CPU’’s idle time status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo;,sizeof(SysPerfInfo),NULL); if (status != NO_ERROR) { return; } // if it’’s a first call - skip it if (m_liOldIdleTime.QuadPart != 0) { // CurrentValue = NewValue - OldValue dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(m_liOldIdleTime); dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(m_liOldSystemTime);
// CurrentCpuIdle = IdleTime / SystemTime
dbIdleTime = dbIdleTime / dbSystemTime;
// CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;
m_fNewUsges = (UINT)dbIdleTime;
}
VC中的自定义消息
Windows 应用程序所要做的每项工作几乎都是基于消息处理的, Windows 系统消息分为常用 Windows 消息,控件通知消息和命令。然而,有时我们需要定义自己的消息来通知程序什么事情发生了,这就是用户自定义消息。 ClassWizard 并没有提供增加用户自定义消息的功能,所以要使用用户自定义消息,必须手工编写代码。然后 ClassWizard 才可以象处理其它消息一样处理你自定义的消息。具体做法如下详解:
第一步:定义消息。一个消息实际上是开发 Windows95 应用程序时, Microsoft 推荐用户自定义消息至少是 WM_USER+100 ,因为很多新控件也要使用 WM_USER 消息。
第二步:实现消息处理函数。该函数使用 WPRAM 和 LPARAM 参数并返回 LPESULT 。
LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam){// TODO: 处理用户自定义消息 AfxMessageBox(“ 处理用户自定义消息 “); return 0;}
第三步:在类头文件的 AFX_MSG 块中说明消息处理函数: class CMainFrame:public CMDIFrameWnd{
…
// 一般消息映射函数
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()}
第四步:在用户类的消息块中,使用 ON_MESSAGE 宏指令将消息映射到消息处理函数中。 BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
ON_WM_CREATE()
ON_WM_TIMER()
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
这样,一个用户自定义消息就可以使用了,如果用户需要一个整个系统唯一的消息,可以调用 SDK 函数 RegisterWindowMessage 并使用 ON_REGISTER_MESSAGE 宏指令取代 ON_MESSAGE 宏指令,其余步骤同上。
VC++ 为程序员提供了一套功能强大、方便快捷的编程工具,它可以帮你方便的生成窗口、菜单等用户界面,可惜就是做出来的东西都一样,没有一点个性。下面,就介绍一些方法,让我们可以按照自己的设计定制出更加符合自己程序风格的窗口。
用.DEF文件导出DLL中的函数
通常我们在调用DLL时所需的DLL文件必须位于以下三个目录之一: (1)Windows的系统目录:\windows\system; (2)DOS中path所指出的任何目录; (3)程序所在的目录。 一、动态链接库的结构
动态链接库中定义有两种函数:导出函数(export function)和内部函数(internal function), 导出函数可以被其它模块调用,内部函数只能在库内部使用。我们在用C++定制动态库文件时, 需要编写的就是包含导出函数表的模块定义文件(.DEF)和实现导出函数功能的C++文件。下面以 Sample.dll为例介绍DEF文件和实现文件的结构。 1.模块定义文件(.DEF)是一个或多个用于描述DLL属性的模块语句组成的文本文件,每个DEF文 件至少必须包含以下模块定义语句: ·第一个语句必须是LIBRARY语句,指出DLL的名字; ·EXPORTS语句列出被导出函数的名字; ·可以使用DESCRIPTION语句描述DLL的用途(此句可选); ·”;”对一行进行注释(可选)。 2.实现文件 实现入口表函数的cpp文件中,包含DLL入口点处理的API函数和导出函数的代码。 二、创建Sample.dll 1.首先创建Sample.dll的工程,启动VC++5.0按以下步骤生成DLL工程: ·在选单中选择File\New\Project; ·在工程列表中选择Win32 Dynamic-Link Library; ·在Project Name中输入工程名:Sample; ·单击Location右边按钮,选择c:\sample目录; ·单击OK完成,至此已创建了Sample.dll的工程文件。 2.创建Sample.def文件: ·在选单中选择File\New\Text File; ·输入以下代码后保存文件名”Sample.def”: ;Sample.def ;指出DLL的名字Sample,链接器将这个名字放到DLL导入库中 LIBRARY Sample ;定义导出函数ShowMe()为例
EXPORTS ShowMe ;def文件结束 3.创建Sample.cpp .在选单中选择File\New\C++ Source File项 .输入以下代码后保存文件名”Sample.cpp” //Sample.cpp #include 〈windows.h〉 int ShowMe(void); //DllEntryPoint为DLL入口点函数,负责初试化并终止DLL BOOL WINAPI DllEntryPoint(HINSTANCE hDLL,DWORD dwReason,LPVOID Reserved) { switch(dwReason) { case DLL-PROCESS-ATTACH: { break; } case DLL-PROCESS-DETACH: { break; } } return TRUE; } int ShowMe(void) { //蜂鸣器响一下 MessageBeep((WORD)-1); MessageBox(“你好!”); return 1; } 4.编译DLL文件 从Build选单中选择Build Sample.DLL,产生Sample.DLL文件,以后就可以随时调用了。 三、在应用程序中调用DLL文件 在应用程序中要首先装入DLL后才能调用导出表中的函数,例如用MFC创建基于对话框的工 程Test,并在对话框上放置”Load”按钮,你就必须添加装载代码。 1.首先在TestDlg.cpp的首部添加变量设置代码: //设置全局变量gLibSample用于存储DLL句柄 HINSTANCE gLibSample=NULL; //第二个变量ShowMe是指向DLL库中ShowMe()函数的指针 typedef int( SHOWME)(void);
SHOWME ShowMe; 2.利用ClassWizard为”Load”按钮添加装载DLL的代码: Void CTestDlg::OnLoadButton() { //要添加的代码如下 if(gLibMyDLL!=NULL) { MessageBox(“The Sample.DLL has already been load.”); return; } //装载Sample.dll,未加路径,将在三个默认路径中寻找 gLibSample=LoadLibrary(“SAMPLE.DLL”); //返回DLL中ShowMe()函数的地址 ShowMe=(SHOWME)GetProcAddress(gLibSample,”ShowMe”); } 3.只要DLL装载成功,在应用程序中就可以直接调用ShowMe()函数(本程序在Windows 95,VC++5.0中运行通过)。
实时时间显示
用计时器实现: SetTimer(1, 1000, NULL); 然后在响应函数: void CAlertDlg::OnTimer(UINT nIDEvent) { static CString strTemp; COleDateTime dtTime;
// 刷新显示的时间 dtTime = COleDateTime::GetCurrentTime(); strTemp.Format(“现在时间 %02i:%02i:%02i “, dtTime.GetHour(), dtTime.GetMinute(), dtTime.GetSecond()); GetDlgItem(IDC_CURTIME)->SetWindowText(strTemp); //IDC_CURTIME即为窗口显示时间的一个 //CEDIT类控件
}

