Wednesday, March 25, 2009

Make Sure Only One Instance of the Application Is Running

Place the following code in your WinMain:

// Look for the running instance of the application
char* szTitle = "My Title";
if (FindWindow(NULL, szTitle)){
SetForegroundWindow(FindWindow(NULL, szTitle));
return FALSE;
}

First, it looks for a window that has the same title as your application. If it finds it, it will make it active.
Another approach is to use a mutex:

BOOL IsFirstInstance()
{
HANDLE hMutex = CreateMutex(NULL, FALSE, "PUT A GUID HERE");
if(hMutex && GetLastError() == ERROR_ALREADY_EXISTS)
{
ReleaseMutex(hMutex);
return FALSE;
}
ReleaseMutex(hMutex);
return TRUE;
}

You call the above-mentioned function in your "InitInstance" method of your application.

How to Launch Internet Properties Control Applet

Use the following code:

WinExec("rundll32 inetcpl.cpl LaunchConnectionDialog", SW_SHOW);

Measure Time In Milliseconds

Use the DWORD GetTickCount(void) function.
The return value is the number of milliseconds that have elapsed since the system was started.
Example Code:

DWORD dwStart = GetTickCount();

Stop if this has taken too long:

if( GetTickCount() - dwStart >= TIMELIMIT )
Cancel();

Measure Time In Milliseconds

Use the DWORD GetTickCount(void); function.


The return value is the number of milliseconds that have elapsed since the system was started.


Example Code:


DWORD dwStart = GetTickCount();



Stop if this has taken too long:


if( GetTickCount() - dwStart >= TIMELIMIT )

Cancel();

Retrieve Menu Item Text with GetMenuItemInfo function


MENUITEMINFO MenuItem;
HMENU hmenu, hsubmenu;
HWND hwnd; //handle to main window
char szString[256];
int countLast =0;
//Initialize MENUITEMINFO structure:
memset(&MenuItem,0, sizeof(MenuItem));
MenuItem.cbSize = sizeof(MenuItem);
MenuItem.fMask =MIIM_TYPE;
MenuItem.fType = MFT_STRING;
//Important - the dwTypeData and cch data members must also be initialized to receive the string.
MenuItem.cch = 256;
MenuItem.dwTypeData = szString;
hmenu = GetMenu(hwnd); //get the menu
hsubmenu = GetSubMenu(hmenu,0); //get the first submenu

countLast = GetMenuItemCount(hsubmenu); //count number of items in the submenu; starts with 0;

GetMenuItemInfo(hsubmenu, 0, --countLast, &MenuItem );

MessageBox(NULL, MenuItem.dwTypeData, "Last Menu Item", MB_OK);

Use Bold or Underlined Font

1. Define a static HFONT variable:

static HFONT hFont;

2. In the response to the WM_INITDIALOG message, create a font with desired features, using CreateFont function:

HFONT CreateFont(
int nHeight, // logical height of font
int nWidth, // logical average character width
int nEscapement, // angle of escapement
int nOrientation, // base-line orientation angle
int fnWeight, // font weight
DWORD fdwItalic, // italic attribute flag
DWORD fdwUnderline, // underline attribute flag
DWORD fdwStrikeOut, // strikeout attribute flag
DWORD fdwCharSet, // character set identifier
DWORD fdwOutputPrecision, // output precision
DWORD fdwClipPrecision, // clipping precision
DWORD fdwQuality, // output quality
DWORD fdwPitchAndFamily, // pitch and family
LPCTSTR lpszFace // pointer to typeface name string
);


Use the pre-defined FW_BOLD parameter for fnWeight for Bold text.
Set fdwUnderline parameter to TRUE for underlined text.

Use default values for most of the other parameters.

Here is a simple helper function:

HFONT SimpleCreateFont( int Height, BOOL Bold, BOOL Italic, BOOL Underline,
BOOL StrikeOut, DWORD Family, char* FaceName )
{
HFONT Ret;
int Weight;
Weight = Bold ? FW_BOLD : FW_NORMAL;
Ret = CreateFont( Height, 0, 0, 0, Weight,
Italic, Underline, StrikeOut, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | Family, FaceName );
return( Ret );
}


3. Use the WM_SETFONT message to tell child control to use new font

SendMessage( GetDlgItem( hwnd, ID_WEB ), WM_SETFONT, (WPARAM)hFont, 0 );

Enable a Button Depending On Whether There is Any Text in the Edit Box

Use this function:

int EntryFieldMessages(HWND hDlg,WPARAM wParam) {
char buffer[1024];
//Get a handle to the button
HWND hIdOk = GetDlgItem(hDlg,1005);
switch (HIWORD(wParam)) {
case EN_CHANGE:
if (GetDlgItemText(hDlg,1004,
buffer, sizeof(buffer))) {
// There is some text in the entry field. Enable the IDOK button.
EnableWindow(hIdOk,1);
}
else // no text, disable the IDOK button
EnableWindow(hIdOk,0);
break;
}
return 1;
}

in response to WM_COMMAND message, i.e.:

case 1004:
{
switch (HIWORD(wParam)){
case EN_CHANGE:
return EntryFieldMessages(hwnd,wParam);
}
break;
}

1004 represents an edit box identifier, of course.

Set Foreground Color to an Individual Edit Box or Static Control

If you have several edit boxes but want to set color to one of them only,
capture the WM_CTLCOLOREDIT message and get the handle to that edit box.


case WM_CTLCOLOREDIT:
//Get Handle to that control first

if((HWND)lParam==GetDlgItem(hwnd,IDC_TEXTBOX)){
HDC hDC = (HDC)wParam;
COLORREF color = RGB(192,0,0); // red color
SetTextColor(hDC, color);
//Optionally, set background color
//SetBkColor(hDC, RGB(255,255,0)); /* yellow */
}
return GetStockObject(WHITE_BRUSH);
break;


For a static control use WM_CTLCOLORSTATIC message:
Example:

HDC hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(255, 0, 0)); //red color


Set the background mode to transparent to use the parent window's background color and return NULL_BRUSH:

SetBkMode(hdcStatic,TRANSPARENT);
return GetStockObject(NULL_BRUSH);


How to Get a Handle to a Control

Use GetDlgItem function:

HWND GetDlgItem(
HWND hDlg, // handle of dialog box
int nIDDlgItem // identifier of control
);

Create A Combo Box on a Toolbar

const int nDropHeight = 100;


Create a dummy button on a toolbar. Separator style recommended.

Command identifier associated with the button:

button.idCommand = CM_DUMMY;

Get the button size:

RECT rect;
SendMessage(g_hToolBar, TB_GETITEMRECT, 8, (LPARAM)&rect);
rect.top = 1;
rect.bottom = rect.top + nDropHeight;


Create a combo box window:

HWND hCombo = CreateWindowEx(0, szComboBox, NULL,
WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST|CBS_HASSTRINGS|CBS_AUTOHSCROLL,
rect.left, rect.top, 100,50,
hwndToolBar, (HMENU)1100, hInst, NULL);

if(hCombo == NULL)
{
MessageBox(0, "Combo Creation Failed!", "Error!",

MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
}

Create Toolbar Tips

Declare:
LPNMTTDISPINFO TTtext;
Example:

case WM_NOTIFY:
TTtext = (LPNMTTDISPINFO)lParam;
if(TTtext->hdr.code==TTN_GETDISPINFO)
switch(TTtext->hdr.idFrom){
case CM_RED_CIRCLE:
TTtext->lpszText = "Red Circle";
break;

case CM_GREEN_SQUARE:
TTtext->lpszText = "Green Square";
break;
case CM_BLUE_CIRCLE:
TTtext->lpszText = "Blue Circle";
break;

case CM_YELLOW_SQUARE:
TTtext->lpszText = "Yellow Square";
break;

}
break;

Tuesday, March 24, 2009

How to Trap Enter key on Edit Box

In order to trap the keypress you'll need to subclass the edit window.
Here's how to do it.
First, you'll need to store the original window proc in a global, so declare it as such:
FAR PROC DefEditProc;

Then you'll need to create a window proc to trap the message. Here's one that will do what you need:

LRESULT CALLBACK MyEditProc(HWND hDlg, UINT message,
WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_CHAR:
if( wParam == 13 ) {
/* User pressed ENTER -- do what you want here. */
return(0);
}
else return( (LRESULT)CallWindowProc
((WNDPROC)DefEditProc,hDlg,message,wParam,lParam) );
break;
default:
return( (LRESULT)CallWindowProc((WNDPROC)DefEditProc,
hDlg,message,wParam,lParam) );
break;
}
return(0);
}


Everything else below should occur when you're initializing the window containing the edit box:

Store the Edit window handle into EditWnd. You can do this several ways...if you created the edit window in a dialog box you can do this:
HWND EditWnd = GetDlgItem(hDlg,IDC_EDIT1);

Otherwise you should already have a handle to the edit window -- just store it in EditWnd. Then do the actual subclassing:

DefEditProc = (WNDPROC)GetWindowLong(EditWnd,GWL_WNDPROC);
SetWindowLong(EditWnd,GWL_WNDPROC,(long)MyEditProc);

Display Last Error


LPVOID lpMsgBuf;
if(SomeHandle==NULL){
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Display the string.
MessageBox( NULL, lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
// Free the buffer.
LocalFree( lpMsgBuf );
}

Attach Menu to Dialog-based Application

1. Create menu resource MYMENU.
2. Use the following code in response to the WM_INITDIALOG message

HMENU hMenu = LoadMenu(hInst, MAKEINTRESOURCE(MYMENU));
SetMenu( hwnd,hMenu);

Retrieving the Path of the Running Application


int GetAppPath(LPTSTR pstr,int length){
int ret,i;
// this gets the name of the running app
ret=GetModuleHandle(NULL,pstr,length);
if(!ret)return 0;
i=lstrlen(pstr)-1;
for(;i>=0;i--){
// replace backslash with a terminating null
if(pstr[i]==TEXT('\\')){
pstr[i]=TEXT('\0');
break;
}
}
return lstrlen(pstr); //return the length of the final string
}

Attach Icon to the Title bar of Dialog-based Application


HICON hIcon = LoadIcon (hInst, MAKEINTRESOURCE (DLG_ICON));
SendMessage (hwnd, WM_SETICON, (WPARAM) ICON_SMALL, (LPARAM) hIcon);