|
desktop html-based client using mfc 7 part 1 - the dialog box (sample will be downloadable soon) |
|
So, why would you need a desktop HTML-based client? You already have the same functionality on your web site! Creating such a client for your customers has many advantages:
In this part of the article, I'll show you how to create an HTML-based dialog box very quickly using MFC, handle its DHTML events, and how to create a tray icon and attach a popup menu to it. Creating the HTML Dialog
MFC 7.0 ships with Visual Studio .NET Visual Studio's wizard would do most of the dialog creation for you:
|
BEGIN_DHTML_EVENT_MAP(CHTMLClientDlg)
DHTML_EVENT_ONCLICK(_T("btnOK"), OnButtonOK)
DHTML_EVENT_ONCLICK(_T("btnCancel"), OnButtonCancel)
END_DHTML_EVENT_MAP()
|
It attaches the DHTML click event for the 2 buttons to 2 functions in your application. Note that it uses the HTML id property to recognize the buttons, so be careful when you edit the HTML file. The DHTML_EVENT_ONCLICK is an MFC macro. There are macros for many DHTML events; check them out at the MFC documentation. You might need to gain access to the WebBrowser Control. This is done using the m_pBrowserApp pointer. I added the following code in the OnInitDialog function, to modify the behavior of the control: |
m_pBrowserApp->put_RegisterAsBrowser(false); m_pBrowserApp->put_RegisterAsDropTarget(false);
|
The first setting prevents link requests from other applications being opened by your application. The second one prevents dragging a URL shortcut into your application window. Adding a Tray Icon A tray icon is a crucial tool in applications such as this. Users want it to be available all the time, but not always as an active window. We'll need to create two functions - one for creating the icon and one for removing it when the application exits. Windows 2000 (and higher) offer more options with version 5 of shell32.dll, such as using a balloon ToolTip instead of the standard one. To enable this, you must set value of the _WIN32_IE constant to 0x0500 (this is in the stdafx.h file). In this example, I'll rely on version 4 only. First, import an icon (16x16 pixels) into your resource file, and set its ID to IDR_TRAY. In the dialog's header file add the following constant (this is our custom message): |
#define WM_TASKBAR WM_APP + 450
|
Then, add the following functions to the dialog's file: |
void CHTMLClientDlg::CreateNotifyIcon()
{
HICON hIcon = AfxGetApp()->LoadIcon(IDR_TRAY);
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = IDR_TRAY;
tnid.dwInfoFlags = NIIF_NONE;
_tcscpy(tnid.szTip, _T("My HTML Client"));
tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
tnid.uCallbackMessage = WM_TASKBAR;
tnid.hIcon = hIcon;
Shell_NotifyIcon(NIM_ADD, &tnid);
if(hIcon)
DestroyIcon(hIcon);
}
void CHTMLClientDlg::RemoveNotifyIcon()
{
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = m_hWnd;
tnid.uID = IDR_TRAY;
Shell_NotifyIcon(NIM_DELETE, &tnid);
}
|
Call these functions from CHTMLClientDlg::OnInitDialog() and CHTMLClientDlg::OnDestroy() respectively. Last thing you may want to do is add a popup menu for the icon. Add the following line to the BEGIN_MESSAGE_MAP section (note that it might appear more than once, for example, if you chose to add an About Box. You need the main dialog's message map). |
ON_MESSAGE(WM_TASKBAR, OnTaskbar)
|
Add an CMenu variable to the class and name it g_hMenu. Also add a menu resource and set its ID to IDR_PUMENU. Put two menu items in it (one for hiding the window and one for closing; name them ID_TRAY_SHOW and ID_TRAY_CLOSE). Next, create the OnTaskbar function to handle the message, and the OnCommand function to handle the popup menu: |
LRESULT CHTMLClientDlg::OnTaskbar(WPARAM wParam, LPARAM lParam)
{
UINT uMouseMsg = (UINT) lParam;
switch(uMouseMsg)
{
case WM_LBUTTONDOWN:
if(IsWindowVisible())
ShowWindow(SW_HIDE);
else
ShowWindow(SW_SHOWNORMAL);
break;
case WM_RBUTTONDOWN:
POINT p;
GetCursorPos(&p);
SetForegroundWindow();
if(g_hMenu)
DestroyMenu(g_hMenu);
CMenu menu;
VERIFY(menu.LoadMenu(IDR_PUMENU));
if(IsWindowVisible())
menu.CheckMenuItem(ID_TRAY_SHOW, MF_CHECKED | MF_BYCOMMAND);
else
menu.CheckMenuItem(ID_TRAY_SHOW, MF_UNCHECKED | MF_BYCOMMAND);
g_hMenu = GetSubMenu(menu, 0);
TrackPopupMenu(g_hMenu, TPM_LEFTBUTTON, p.x, p.y, 0, m_hWnd, NULL);
break;
}
return 0;
}
BOOL CHTMLClientDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{
case ID_TRAY_SHOW:
if(IsWindowVisible())
ShowWindow(SW_HIDE);
else
ShowWindow(SW_SHOWNORMAL);
break;
case ID_TRAY_CLOSE:
OnOK();
break;
default:
break;
}
return 0;
}
|
If you want the window to hide and not close when you click the "X" button, modify the CHTMLClientDlg::OnSysCommand function as follows: |
if(nID == SC_CLOSE) { ShowWindow(SW_HIDE); } else { CDHtmlDialog::OnSysCommand(nID, lParam); }
|
And you're done!
The next part will deal with data synchronization using XML Web Services, and I'll also show you how to easily create an automatic update for the application. |
