Introduction
This article is a rework of the idea from an existing article but with the focus on usability and ease of use.
This utility creates unique preprocessor macros to prevent multiple header inclusion. If a filename is specified as a command line argument or a file is dropped onto the dialog, it's name is also included in the macro.
The dialog stays "always on top," accepts dropped shortcuts, snaps to screen edges and can be dragged by its surface. Upon entering a key/OK button, the displayed macro is copied to the clipboard, and the program exits.
Usage
The program is designed to be used from inside VC 2005/2008 IDE to generate a unique macro for the currently opened file:
The Code
A unique macro is generated from 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;
}
When sending the text to a clipboard, it is necessary to use the HWND of the dialog in OpenClipboard
, as stated in MSDN:
"If an application calls OpenClipboard
with hwnd
set to NULL
, EmptyClipboard
sets the clipboard owner to NULL
; this causes SetClipboardData
to fail."
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; GlobalUnlock(hglbCopy);
if (NULL==::SetClipboardData(CF_UNICODETEXT,
hglbCopy)) MessageBeep(-1);
}
else retVal=false;
::CloseClipboard();
}
else retVal=false;
return retVal;
}
The font for the edit control is created by retrieving the info about current default font and modifying its properties. The edit control is read-only, so the default background color (white) is restored by handling the WM_CTLCOLORSTATIC
message:
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);
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);
}
The dialog background color is changed by handling WM_CTLCOLORDLG
and returning previously created brush of desired color:
#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;
}
The focus in the dialog form has the OK button, set by calling GotoDlgCtrl(GetDlgItem(IDOK))
and returning FALSE
in CMainDlg::OnInitDialog
.
Dropped shortcuts are resolved using the function assembled by Igor Vigdorchik. I will leave other features in the code as a readers' exercise.
The project is built with VC 2008 Express, Windows SDK 6.1, WTL 8.0 and ATL 3.0 from Platform SDK R2.