C++ Header Guard
创建独特的预处理器宏来防止头文件重复包含。

引言
本文是对 现有文章 的重构,但重点在于可用性和易用性。
此工具创建独特的预处理器宏来防止头文件重复包含。如果命令行中指定了文件名,或者将文件拖放到对话框中,则文件名也会包含在宏中。
对话框始终位于最顶层,接受拖放的快捷方式,可以吸附到屏幕边缘,并且可以通过其表面进行拖动。在输入密钥/确定按钮后,显示的宏将被复制到剪贴板,程序退出。
用法
该程序设计用于在 VC 2005/2008 IDE 内部使用,以生成当前打开文件的唯一宏。
代码
唯一的宏由 GUID 生成。
CString CIncludeGen::CreateGuid()
{
TCHAR fmtGuid[] = _T("%08lx_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x");
GUID guid;
CoCreateGuid(&guid);
CString str;
str.Format(fmtGuid, guid.Data1,guid.Data2,guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
str.MakeUpper();
return str;
}
将文本发送到剪贴板时,必须使用对话框的 HWND 在 OpenClipboard
中,如 MSDN 中所述。
“如果应用程序使用 hwnd
设置为 NULL
调用 OpenClipboard
,则 EmptyClipboard
会将剪贴板所有者设置为 NULL
;这将导致 SetClipboardData
失败。”
bool CIncludeGen::copy2clipboard(HWND clipbrdowner)
{
if (m_text.IsEmpty()) return false;
bool retVal=true;
if(::OpenClipboard(clipbrdowner))
{
LPTSTR lptstrCopy;
LPCTSTR txt=m_text;
HGLOBAL hglbCopy;
::EmptyClipboard();
hglbCopy = GlobalAlloc(GMEM_MOVEABLE,
(m_text.GetLength() + 1) * sizeof(TCHAR));
if (hglbCopy != NULL)
{
lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
memcpy(lptstrCopy, txt,
(m_text.GetLength() * sizeof(TCHAR)));
lptstrCopy[m_text.GetLength()] = (TCHAR) 0; // null character
GlobalUnlock(hglbCopy);
if (NULL==::SetClipboardData(CF_UNICODETEXT,
hglbCopy)) MessageBeep(-1);
}
else retVal=false;
::CloseClipboard();
}
else retVal=false;
return retVal;
}
编辑控件的字体是通过检索当前默认字体的相关信息并修改其属性来创建的。编辑控件是只读的,因此默认背景色(白色)是通过处理 WM_CTLCOLORSTATIC
消息来恢复的。
bool CMainDlg::createEditCtlFont()
{
m_editCtlFont=(HFONT)GetStockObject(DEFAULT_GUI_FONT);
if (m_editCtlFont.IsNull()) return false;
LOGFONT lfont={0};
if (0==GetObject(m_editCtlFont,sizeof(LOGFONT), &lfont)) return false;
if (IsClearTypeEnabled()) lfont.lfQuality=CLEARTYPE_QUALITY;
lfont.lfPitchAndFamily=FIXED_PITCH | FF_MODERN;
WCHAR fn[32]=L"Courier New";
lfont.lfHeight=(LONG)(lfont.lfHeight*1.15);//increase size a bit
memcpy(lfont.lfFaceName, fn, _countof(fn));
m_editCtlFont.DeleteObject();
if (NULL==m_editCtlFont.CreateFontIndirect(&lfont)) return false;
return true;
}
...
LRESULT CMainDlg::OnCtlColor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if (((HWND)lParam)==GetDlgItem( IDC_EDIT1 )) return (LRESULT)GetStockObject(
WHITE_BRUSH );
return ::DefWindowProc(m_hWnd, wParam, lParam, bHandled);
}
对话框背景色是通过处理 WM_CTLCOLORDLG
并返回先前创建的所需颜色的画笔来更改的。
#define INCLHG_DLG_BKGCOLOR RGB(198,209,223)
...
CMainDlg::CMainDlg()
{
m_dialogbrush.CreateSolidBrush(INCLHG_DLG_BKGCOLOR);...
LRESULT CMainDlg::OnMainDialogColor(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL& bHandled)
{
return (LRESULT)m_dialogbrush.m_hBrush;
}
对话框表单中的焦点设置为确定按钮,方法是调用 GotoDlgCtrl(GetDlgItem(IDOK))
并在 CMainDlg::OnInitDialog
中返回 FALSE
。
使用 Igor Vigdorchik 编写的函数 解析拖放的快捷方式。我将把其他功能留给读者作为练习。
该项目使用 VC 2008 Express、Windows SDK 6.1、WTL 8.0 和 Platform SDK R2 中的 ATL 3.0 构建。