Back to index

lightning-sunbird  0.9+nobinonly
winEmbed.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: Mozilla-sample-code 1.0
00004  *
00005  * Copyright (c) 2002 Netscape Communications Corporation and
00006  * other contributors
00007  *
00008  * Permission is hereby granted, free of charge, to any person obtaining a
00009  * copy of this Mozilla sample software and associated documentation files
00010  * (the "Software"), to deal in the Software without restriction, including
00011  * without limitation the rights to use, copy, modify, merge, publish,
00012  * distribute, sublicense, and/or sell copies of the Software, and to permit
00013  * persons to whom the Software is furnished to do so, subject to the
00014  * following conditions:
00015  *
00016  * The above copyright notice and this permission notice shall be included
00017  * in all copies or substantial portions of the Software.
00018  *
00019  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00020  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00021  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00022  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00023  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00024  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00025  * DEALINGS IN THE SOFTWARE.
00026  *
00027  * Contributor(s):
00028  *   Doug Turner <dougt@netscape.com>
00029  *   Adam Lock <adamlock@netscape.com>
00030  *
00031  * ***** END LICENSE BLOCK ***** */
00032 
00033 #include <stdio.h>
00034 
00035 // C RunTime Header Files
00036 #include <stdlib.h>
00037 #include <malloc.h>
00038 #include <memory.h>
00039 #include <tchar.h>
00040 
00041 // Win32 header files
00042 #include <windows.h>
00043 #include <commctrl.h>
00044 #include <commdlg.h>
00045 
00046 // Mozilla header files
00047 #include "nsEmbedAPI.h"
00048 #include "nsIClipboardCommands.h"
00049 #include "nsXPIDLString.h"
00050 #include "nsIWebBrowserPersist.h"
00051 #include "nsIWebBrowserFocus.h"
00052 #include "nsIWindowWatcher.h"
00053 #include "nsIObserverService.h"
00054 #include "nsIObserver.h"
00055 #include "nsIURI.h"
00056 #include "plstr.h"
00057 #include "nsIInterfaceRequestor.h"
00058 
00059 #include "nsDirectoryService.h"
00060 #include "nsDirectoryServiceDefs.h"
00061 #include "nsProfileDirServiceProvider.h"
00062 #include "nsAppDirectoryServiceDefs.h"
00063 
00064 // Local header files
00065 #include "winEmbed.h"
00066 #include "WebBrowserChrome.h"
00067 #include "WindowCreator.h"
00068 #include "resource.h"
00069 #include "nsStaticComponents.h"
00070 
00071 // Printing header files
00072 #include "nsIPrintSettings.h"
00073 #include "nsIWebBrowserPrint.h"
00074 
00075 
00076 #define MAX_LOADSTRING 100
00077 
00078 
00079 #ifndef _BUILD_STATIC_BIN
00080 nsStaticModuleInfo const *const kPStaticModules = nsnull;
00081 PRUint32 const kStaticModuleCount = 0;
00082 #endif
00083 
00084 const TCHAR *szWindowClass = _T("WINEMBED");
00085 
00086 // Foward declarations of functions included in this code module:
00087 static ATOM             MyRegisterClass(HINSTANCE hInstance);
00088 static LRESULT CALLBACK BrowserWndProc(HWND, UINT, WPARAM, LPARAM);
00089 static BOOL    CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
00090 
00091 static nsresult InitializeWindowCreator();
00092 static nsresult OpenWebPage(const char * url);
00093 static nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome);
00094 
00095 // Profile chooser stuff
00096 static nsresult StartupProfile();
00097 
00098 // Global variables
00099 static UINT gDialogCount = 0;
00100 static HINSTANCE ghInstanceResources = NULL;
00101 static HINSTANCE ghInstanceApp = NULL;
00102 static char gFirstURL[1024];
00103 
00104 // A list of URLs to populate the URL drop down list with
00105 static const TCHAR *gDefaultURLs[] = 
00106 {
00107     _T("http://www.mozilla.org/"),
00108     _T("http://www.netscape.com/"),
00109     _T("http://browsertest.web.aol.com/tests/javascript/javascpt/index.htm"),
00110     _T("http://127.0.0.1/"),
00111     _T("http://www.yahoo.com/"),
00112     _T("http://www.travelocity.com/"),
00113     _T("http://www.disney.com/"),
00114     _T("http://www.go.com/"),
00115     _T("http://www.google.com/"),
00116     _T("http://www.ebay.com/"),
00117     _T("http://www.shockwave.com/"),
00118     _T("http://www.slashdot.org/"),
00119     _T("http://www.quicken.com/"),
00120     _T("http://www.hotmail.com/"),
00121     _T("http://www.cnn.com/"),
00122     _T("http://www.javasoft.com/")
00123 };
00124 int main(int argc, char *argv[])
00125 {
00126     printf("You are embedded, man!\n\n");
00127     printf("******************************************************************\n");
00128     printf("*                                                                *\n");
00129     printf("*  IMPORTANT NOTE:                                               *\n");
00130     printf("*                                                                *\n");
00131     printf("*  WinEmbed is not supported!!! Do not raise bugs on it unless   *\n");
00132     printf("*  it is badly broken (e.g. crash on start/exit, build errors)   *\n");
00133     printf("*  or you have the patch to make it better! MFCEmbed is now our  *\n");
00134     printf("*  embedding test application on Win32 and all testing should    *\n");
00135     printf("*  be done on that.                                              *\n");
00136     printf("*                                                                *\n");
00137     printf("******************************************************************\n");
00138     printf("\n\n");
00139     
00140     // Sophisticated command-line parsing in action
00141 #ifdef MINIMO
00142     char *szFirstURL = "http://www.mozilla.org/projects/embedding";
00143 #else
00144     char *szFirstURL = "http://www.mozilla.org/projects/minimo";
00145 #endif
00146        int argn;
00147     for (argn = 1; argn < argc; argn++)
00148     {
00149               szFirstURL = argv[argn];
00150     }
00151     strncpy(gFirstURL, szFirstURL, sizeof(gFirstURL) - 1);
00152 
00153     ghInstanceApp = GetModuleHandle(NULL);
00154     ghInstanceResources = GetModuleHandle(NULL);
00155 
00156     // Initialize global strings
00157     TCHAR szTitle[MAX_LOADSTRING];
00158     LoadString(ghInstanceResources, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
00159     MyRegisterClass(ghInstanceApp);
00160 
00161     // Init Embedding APIs
00162     NS_InitEmbedding(nsnull, nsnull, kPStaticModules, kStaticModuleCount);
00163 
00164     // Choose the new profile
00165     if (NS_FAILED(StartupProfile()))
00166     {
00167         NS_TermEmbedding();
00168         return 1;
00169     }
00170     WPARAM rv;
00171     {   
00172               InitializeWindowCreator();
00173 
00174         // Open the initial browser window
00175         OpenWebPage(gFirstURL);
00176 
00177         // Main message loop.
00178         // NOTE: We use a fake event and a timeout in order to process idle stuff for
00179         //       Mozilla every 1/10th of a second.
00180         PRBool runCondition = PR_TRUE;
00181 
00182         rv = AppCallbacks::RunEventLoop(runCondition);
00183     }
00184     // Close down Embedding APIs
00185     NS_TermEmbedding();
00186 
00187     return rv;
00188 }
00189 
00190 /* InitializeWindowCreator creates and hands off an object with a callback
00191    to a window creation function. This is how all new windows are opened,
00192    except any created directly by the embedding app. */
00193 nsresult InitializeWindowCreator()
00194 {
00195     // create an nsWindowCreator and give it to the WindowWatcher service
00196     WindowCreator *creatorCallback = new WindowCreator();
00197     if (creatorCallback)
00198     {
00199         nsCOMPtr<nsIWindowCreator> windowCreator(NS_STATIC_CAST(nsIWindowCreator *, creatorCallback));
00200         if (windowCreator)
00201         {
00202             nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
00203             if (wwatch)
00204             {
00205                 wwatch->SetWindowCreator(windowCreator);
00206                 return NS_OK;
00207             }
00208         }
00209     }
00210     return NS_ERROR_FAILURE;
00211 }
00212 
00213 //-----------------------------------------------------------------------------
00214 
00215 //
00216 //  FUNCTION: OpenWebPage()
00217 //
00218 //  PURPOSE: Opens a new browser dialog and starts it loading to the
00219 //           specified url.
00220 //
00221 nsresult OpenWebPage(const char *url)
00222 {
00223     nsresult  rv;
00224 
00225     // Create the chrome object. Note that it leaves this function
00226     // with an extra reference so that it can released correctly during
00227     // destruction (via Win32UI::Destroy)
00228 
00229     nsCOMPtr<nsIWebBrowserChrome> chrome;
00230     rv = AppCallbacks::CreateBrowserWindow(nsIWebBrowserChrome::CHROME_ALL,
00231            nsnull, getter_AddRefs(chrome));
00232     if (NS_SUCCEEDED(rv))
00233     {
00234         // Start loading a page
00235         nsCOMPtr<nsIWebBrowser> newBrowser;
00236         chrome->GetWebBrowser(getter_AddRefs(newBrowser));
00237         nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(newBrowser));
00238         return webNav->LoadURI(NS_ConvertASCIItoUCS2(url).get(),
00239                                nsIWebNavigation::LOAD_FLAGS_NONE,
00240                                nsnull,
00241                                nsnull,
00242                                nsnull);
00243     }
00244 
00245     return rv;
00246 }   
00247 
00248 //
00249 //  FUNCTION: GetBrowserFromChrome()
00250 //
00251 //  PURPOSE: Returns the HWND for the webbrowser container associated
00252 //           with the specified chrome.
00253 //
00254 HWND GetBrowserFromChrome(nsIWebBrowserChrome *aChrome)
00255 {
00256     if (!aChrome)
00257     {
00258         return NULL;
00259     }
00260     nsCOMPtr<nsIEmbeddingSiteWindow> baseWindow = do_QueryInterface(aChrome);
00261     HWND hwnd = NULL;
00262     baseWindow->GetSiteWindow((void **) & hwnd);
00263     return hwnd;
00264 }
00265 
00266 
00267 //
00268 //  FUNCTION: GetBrowserDlgFromChrome()
00269 //
00270 //  PURPOSE: Returns the HWND for the browser dialog associated with
00271 //           the specified chrome.
00272 //
00273 HWND GetBrowserDlgFromChrome(nsIWebBrowserChrome *aChrome)
00274 {
00275     return GetParent(GetBrowserFromChrome(aChrome));
00276 }
00277 
00278 
00279 //
00280 //  FUNCTION: SaveWebPage()
00281 //
00282 //  PURPOSE: Saves the contents of the web page to a file
00283 //
00284 void SaveWebPage(nsIWebBrowser *aWebBrowser)
00285 {
00286     // Use the browser window title as the initial file name
00287     nsCOMPtr<nsIBaseWindow> webBrowserAsWin = do_QueryInterface(aWebBrowser);
00288     nsXPIDLString windowTitle;
00289     webBrowserAsWin->GetTitle(getter_Copies(windowTitle));
00290     nsCString fileName; fileName.AssignWithConversion(windowTitle);
00291 
00292     // Sanitize the title of all illegal characters
00293     fileName.CompressWhitespace();     // Remove whitespace from the ends
00294     fileName.StripChars("\\*|:\"><?"); // Strip illegal characters
00295     fileName.ReplaceChar('.', L'_');   // Dots become underscores
00296     fileName.ReplaceChar('/', L'-');   // Forward slashes become hyphens
00297 
00298     // Copy filename to a character buffer
00299     char szFile[_MAX_PATH];
00300     memset(szFile, 0, sizeof(szFile));
00301     PL_strncpyz(szFile, fileName.get(), sizeof(szFile) - 1); // XXXldb probably should be just sizeof(szfile)
00302 
00303     // Initialize the file save as information structure
00304     OPENFILENAME saveFileNameInfo;
00305     memset(&saveFileNameInfo, 0, sizeof(saveFileNameInfo));
00306     saveFileNameInfo.lStructSize = sizeof(saveFileNameInfo);
00307     saveFileNameInfo.hwndOwner = NULL;
00308     saveFileNameInfo.hInstance = NULL;
00309     saveFileNameInfo.lpstrFilter =
00310         "Web Page, HTML Only (*.htm;*.html)\0*.htm;*.html\0"
00311         "Web Page, Complete (*.htm;*.html)\0*.htm;*.html\0"
00312         "Text File (*.txt)\0*.txt\0"; 
00313     saveFileNameInfo.lpstrCustomFilter = NULL; 
00314     saveFileNameInfo.nMaxCustFilter = NULL; 
00315     saveFileNameInfo.nFilterIndex = 1; 
00316     saveFileNameInfo.lpstrFile = szFile; 
00317     saveFileNameInfo.nMaxFile = sizeof(szFile); 
00318     saveFileNameInfo.lpstrFileTitle = NULL;
00319     saveFileNameInfo.nMaxFileTitle = 0; 
00320     saveFileNameInfo.lpstrInitialDir = NULL; 
00321     saveFileNameInfo.lpstrTitle = NULL; 
00322     saveFileNameInfo.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; 
00323     saveFileNameInfo.nFileOffset = NULL; 
00324     saveFileNameInfo.nFileExtension = NULL; 
00325     saveFileNameInfo.lpstrDefExt = "htm"; 
00326     saveFileNameInfo.lCustData = NULL; 
00327     saveFileNameInfo.lpfnHook = NULL; 
00328     saveFileNameInfo.lpTemplateName = NULL; 
00329 
00330     if (GetSaveFileName(&saveFileNameInfo))
00331     {
00332         // Does the user want to save the complete document including
00333         // all frames, images, scripts, stylesheets etc. ?
00334         char *pszDataPath = NULL;
00335         if (saveFileNameInfo.nFilterIndex == 2) // 2nd choice means save everything
00336         {
00337             static char szDataFile[_MAX_PATH];
00338             char szDataPath[_MAX_PATH];
00339             char drive[_MAX_DRIVE];
00340             char dir[_MAX_DIR];
00341             char fname[_MAX_FNAME];
00342             char ext[_MAX_EXT];
00343 
00344             _splitpath(szFile, drive, dir, fname, ext);
00345             sprintf(szDataFile, "%s_files", fname);
00346             _makepath(szDataPath, drive, dir, szDataFile, "");
00347 
00348             pszDataPath = szDataPath;
00349        }
00350 
00351         // Save away
00352         nsCOMPtr<nsIWebBrowserPersist> persist(do_QueryInterface(aWebBrowser));
00353 
00354         nsCOMPtr<nsILocalFile> file;
00355         NS_NewNativeLocalFile(nsDependentCString(szFile), TRUE, getter_AddRefs(file));
00356 
00357         nsCOMPtr<nsILocalFile> dataPath;
00358         if (pszDataPath)
00359         {
00360             NS_NewNativeLocalFile(nsDependentCString(pszDataPath), TRUE, getter_AddRefs(dataPath));
00361         }
00362 
00363         persist->SaveDocument(nsnull, file, dataPath, nsnull, 0, 0);
00364     }
00365 }
00366 
00367 
00368 //
00369 //  FUNCTION: ResizeEmbedding()
00370 //
00371 //  PURPOSE: Resizes the webbrowser window to fit its container.
00372 //
00373 nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome)
00374 {
00375     if (!chrome)
00376         return NS_ERROR_FAILURE;
00377     
00378     nsCOMPtr<nsIEmbeddingSiteWindow> embeddingSite = do_QueryInterface(chrome);
00379     HWND hWnd;
00380     embeddingSite->GetSiteWindow((void **) & hWnd);
00381     
00382     if (!hWnd)
00383         return NS_ERROR_NULL_POINTER;
00384     
00385     RECT rect;
00386     GetClientRect(hWnd, &rect);
00387     
00388     // Make sure the browser is visible and sized
00389     nsCOMPtr<nsIWebBrowser> webBrowser;
00390     chrome->GetWebBrowser(getter_AddRefs(webBrowser));
00391     nsCOMPtr<nsIBaseWindow> webBrowserAsWin = do_QueryInterface(webBrowser);
00392     if (webBrowserAsWin)
00393     {
00394         webBrowserAsWin->SetPositionAndSize(rect.left, 
00395                                    rect.top, 
00396                                    rect.right - rect.left, 
00397                                    rect.bottom - rect.top,
00398                                    PR_TRUE);
00399         webBrowserAsWin->SetVisibility(PR_TRUE);
00400     }
00401 
00402     return NS_OK;
00403 }
00404 
00405 
00406 //
00407 //  FUNCTION: MyRegisterClass()
00408 //
00409 //  PURPOSE: Registers the window class.
00410 //
00411 //  COMMENTS:
00412 //
00413 //    This function and its usage is only necessary if you want this code
00414 //    to be compatible with Win32 systems prior to the 'RegisterClassEx'
00415 //    function that was added to Windows 95. It is important to call this function
00416 //    so that the application will get 'well formed' small icons associated
00417 //    with it.
00418 //
00419 ATOM MyRegisterClass(HINSTANCE hInstance)
00420 {
00421     WNDCLASSEX wcex;
00422 
00423     memset(&wcex, 0, sizeof(wcex));
00424     wcex.cbSize = sizeof(WNDCLASSEX); 
00425 
00426     wcex.style            = CS_HREDRAW | CS_VREDRAW;
00427     wcex.lpfnWndProc    = (WNDPROC) BrowserWndProc;
00428     wcex.cbClsExtra        = 0;
00429     wcex.cbWndExtra        = 0;
00430     wcex.hInstance        = hInstance;
00431     wcex.hIcon            = LoadIcon(ghInstanceResources, (LPCTSTR)IDI_WINEMBED);
00432     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
00433     wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
00434     wcex.lpszClassName    = szWindowClass;
00435     wcex.hIconSm        = LoadIcon(ghInstanceResources, (LPCTSTR)IDI_SMALL);
00436 
00437     return RegisterClassEx(&wcex);
00438 }
00439 
00440 
00441 //
00442 //  FUNCTION: UpdateUI()
00443 //
00444 //  PURPOSE: Refreshes the buttons and menu items in the browser dialog
00445 //
00446 void UpdateUI(nsIWebBrowserChrome *aChrome)
00447 {
00448     HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
00449     nsCOMPtr<nsIWebBrowser> webBrowser;
00450     nsCOMPtr<nsIWebNavigation> webNavigation;
00451     aChrome->GetWebBrowser(getter_AddRefs(webBrowser));
00452     webNavigation = do_QueryInterface(webBrowser);
00453 
00454     PRBool canGoBack = PR_FALSE;
00455     PRBool canGoForward = PR_FALSE;
00456     if (webNavigation)
00457     {
00458         webNavigation->GetCanGoBack(&canGoBack);
00459         webNavigation->GetCanGoForward(&canGoForward);
00460     }
00461 
00462     PRBool canCutSelection = PR_FALSE;
00463     PRBool canCopySelection = PR_FALSE;
00464     PRBool canPaste = PR_FALSE;
00465 
00466     nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
00467     if (clipCmds)
00468     {
00469         clipCmds->CanCutSelection(&canCutSelection);
00470         clipCmds->CanCopySelection(&canCopySelection);
00471         clipCmds->CanPaste(&canPaste);
00472     }
00473 
00474     HMENU hmenu = GetMenu(hwndDlg);
00475     if (hmenu)
00476     {
00477         EnableMenuItem(hmenu, MOZ_GoBack, MF_BYCOMMAND |
00478             ((canGoBack) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
00479         EnableMenuItem(hmenu, MOZ_GoForward, MF_BYCOMMAND |
00480             ((canGoForward) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
00481 
00482         EnableMenuItem(hmenu, MOZ_Cut, MF_BYCOMMAND |
00483             ((canCutSelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
00484         EnableMenuItem(hmenu, MOZ_Copy, MF_BYCOMMAND |
00485             ((canCopySelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
00486         EnableMenuItem(hmenu, MOZ_Paste, MF_BYCOMMAND |
00487             ((canPaste) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
00488     }
00489 
00490     HWND button;
00491     button = GetDlgItem(hwndDlg, IDC_BACK);
00492     if (button)
00493       EnableWindow(button, canGoBack);
00494     button = GetDlgItem(hwndDlg, IDC_FORWARD);
00495     if (button)
00496       EnableWindow(button, canGoForward);
00497 }
00498 
00499 
00500 //
00501 //  FUNCTION: BrowserDlgProc()
00502 //
00503 //  PURPOSE: Browser dialog windows message handler.
00504 //
00505 //  COMMENTS:
00506 //
00507 //    The code for handling buttons and menu actions is here.
00508 //
00509 BOOL CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
00510 {
00511     // Get the browser and other pointers since they are used a lot below
00512     HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
00513     nsIWebBrowserChrome *chrome = nsnull ;
00514     if (hwndBrowser)
00515     {
00516         chrome = (nsIWebBrowserChrome *) GetWindowLong(hwndBrowser, GWL_USERDATA);
00517     }
00518     nsCOMPtr<nsIWebBrowser> webBrowser;
00519     nsCOMPtr<nsIWebNavigation> webNavigation;
00520     nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint;
00521     if (chrome)
00522     {
00523         chrome->GetWebBrowser(getter_AddRefs(webBrowser));
00524         webNavigation = do_QueryInterface(webBrowser);
00525         webBrowserPrint = do_GetInterface(webBrowser);
00526     }
00527 
00528     // Test the message
00529     switch (uMsg)
00530     {
00531     case WM_INITDIALOG:
00532         return TRUE;
00533 
00534     case WM_INITMENU:
00535         UpdateUI(chrome);
00536         return TRUE;
00537 
00538     case WM_SYSCOMMAND:
00539         if (wParam == SC_CLOSE)
00540         {
00541             WebBrowserChromeUI::Destroy(chrome);
00542             return TRUE;
00543         }
00544         break;
00545 
00546     case WM_DESTROY:
00547         return TRUE;
00548 
00549     case WM_COMMAND:
00550         if (!webBrowser)
00551         {
00552             return TRUE;
00553         }
00554 
00555         // Test which command was selected
00556         switch (LOWORD(wParam))
00557         {
00558         case IDC_ADDRESS:
00559             if (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE)
00560             {
00561                 // User has changed the address field so enable the Go button
00562                 EnableWindow(GetDlgItem(hwndDlg, IDC_GO), TRUE);
00563             }
00564             break;
00565 
00566         case IDC_GO:
00567             {
00568                 TCHAR szURL[2048];
00569                 memset(szURL, 0, sizeof(szURL));
00570                 GetDlgItemText(hwndDlg, IDC_ADDRESS, szURL,
00571                     sizeof(szURL) / sizeof(szURL[0]) - 1);
00572                 webNavigation->LoadURI(
00573                     NS_ConvertASCIItoUCS2(szURL).get(),
00574                     nsIWebNavigation::LOAD_FLAGS_NONE,
00575                     nsnull,
00576                     nsnull,
00577                     nsnull);
00578             }
00579             break;
00580 
00581         case IDC_STOP:
00582             webNavigation->Stop(nsIWebNavigation::STOP_ALL);
00583             UpdateUI(chrome);
00584             break;
00585 
00586         case IDC_RELOAD:
00587             webNavigation->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
00588             break;
00589 
00590         case IDM_EXIT:
00591             PostMessage(hwndDlg, WM_SYSCOMMAND, SC_CLOSE, 0);
00592             break;
00593 
00594         // File menu commands
00595 
00596         case MOZ_NewBrowser:
00597             OpenWebPage(gFirstURL);
00598             break;
00599 
00600         case MOZ_Save:
00601             SaveWebPage(webBrowser);
00602             break;
00603 
00604         case MOZ_Print:
00605             {
00606                 // NOTE: Embedding code shouldn't need to get the docshell or
00607                 //       contentviewer AT ALL. This code below will break one
00608                 //       day but will have to do until the embedding API has
00609                 //       a cleaner way to do the same thing.
00610               if (webBrowserPrint)
00611               {
00612                   nsCOMPtr<nsIPrintSettings> printSettings;
00613                   webBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings));
00614                   NS_ASSERTION(printSettings, "You can't PrintPreview without a PrintSettings!");
00615                   if (printSettings) 
00616                   {
00617                       printSettings->SetPrintSilent(PR_TRUE);
00618                       webBrowserPrint->Print(printSettings, (nsIWebProgressListener*)nsnull);
00619                   }
00620               }
00621             }
00622             break;
00623 
00624         // Edit menu commands
00625 
00626         case MOZ_Cut:
00627             {
00628                 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
00629                 clipCmds->CutSelection();
00630             }
00631             break;
00632 
00633         case MOZ_Copy:
00634             {
00635                 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
00636                 clipCmds->CopySelection();
00637             }
00638             break;
00639 
00640         case MOZ_Paste:
00641             {
00642                 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
00643                 clipCmds->Paste();
00644             }
00645             break;
00646 
00647         case MOZ_SelectAll:
00648             {
00649                 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
00650                 clipCmds->SelectAll();
00651             }
00652             break;
00653 
00654         case MOZ_SelectNone:
00655             {
00656                 nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser);
00657                 clipCmds->SelectNone();
00658             }
00659             break;
00660 
00661         // Go menu commands
00662         case IDC_BACK:
00663         case MOZ_GoBack:
00664             webNavigation->GoBack();
00665             UpdateUI(chrome);
00666             break;
00667 
00668         case IDC_FORWARD:
00669         case MOZ_GoForward:
00670             webNavigation->GoForward();
00671             UpdateUI(chrome);
00672             break;
00673 
00674         // Help menu commands
00675         case MOZ_About:
00676             {
00677                 TCHAR szAboutTitle[MAX_LOADSTRING];
00678                 TCHAR szAbout[MAX_LOADSTRING];
00679                 LoadString(ghInstanceResources, IDS_ABOUT_TITLE, szAboutTitle, MAX_LOADSTRING);
00680                 LoadString(ghInstanceResources, IDS_ABOUT, szAbout, MAX_LOADSTRING);
00681                 MessageBox(NULL, szAbout, szAboutTitle, MB_OK);
00682             }
00683             break;
00684         }
00685 
00686         return TRUE;
00687 
00688     case WM_ACTIVATE:
00689         {
00690             nsCOMPtr<nsIWebBrowserFocus> focus(do_GetInterface(webBrowser));
00691             if(focus)
00692             {
00693                 switch (wParam)
00694                 {
00695                 case WA_ACTIVE:
00696                     focus->Activate();
00697                     break;
00698                 case WA_INACTIVE:
00699                     focus->Deactivate();
00700                     break;
00701                 default:
00702                     break;
00703                 }
00704             }
00705         }
00706         break;
00707 
00708     case WM_SIZE:
00709         {
00710             UINT newDlgWidth = LOWORD(lParam);
00711             UINT newDlgHeight = HIWORD(lParam);
00712 
00713             // TODO Reposition the control bar - for the moment it's fixed size
00714 
00715             // Reposition the status area. Status bar
00716             // gets any space that the fixed size progress bar doesn't use.
00717             int progressWidth;
00718             int statusWidth;
00719             int statusHeight;
00720             HWND hwndStatus = GetDlgItem(hwndDlg, IDC_STATUS);
00721             if (hwndStatus) {
00722               RECT rcStatus;
00723               GetWindowRect(hwndStatus, &rcStatus);
00724               statusHeight = rcStatus.bottom - rcStatus.top;
00725             } else
00726               statusHeight = 0;
00727 
00728             HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
00729             if (hwndProgress) {
00730               RECT rcProgress;
00731               GetWindowRect(hwndProgress, &rcProgress);
00732               progressWidth = rcProgress.right - rcProgress.left;
00733             } else
00734               progressWidth = 0;
00735             statusWidth = newDlgWidth - progressWidth;
00736 
00737             if (hwndStatus)
00738               SetWindowPos(hwndStatus,
00739                            HWND_TOP,
00740                            0, newDlgHeight - statusHeight,
00741                            statusWidth,
00742                            statusHeight,
00743                            SWP_NOZORDER);
00744             if (hwndProgress)
00745               SetWindowPos(hwndProgress,
00746                            HWND_TOP,
00747                            statusWidth, newDlgHeight - statusHeight,
00748                            0, 0,
00749                            SWP_NOSIZE | SWP_NOZORDER);
00750 
00751             // Resize the browser area (assuming the browse is
00752             // sandwiched between the control bar and status area)
00753             RECT rcBrowser;
00754             POINT ptBrowser;
00755             GetWindowRect(hwndBrowser, &rcBrowser);
00756             ptBrowser.x = rcBrowser.left;
00757             ptBrowser.y = rcBrowser.top;
00758             ScreenToClient(hwndDlg, &ptBrowser);
00759             int browserHeight = newDlgHeight - ptBrowser.y - statusHeight;
00760             if (browserHeight < 1)
00761             {
00762                 browserHeight = 1;
00763             }
00764             SetWindowPos(hwndBrowser,
00765                          HWND_TOP,
00766                          0, 0,
00767                          newDlgWidth,
00768                          newDlgHeight - ptBrowser.y - statusHeight,
00769                          SWP_NOMOVE | SWP_NOZORDER);
00770         }
00771         return TRUE;
00772     }
00773     return FALSE;
00774 }
00775 
00776 
00777 //
00778 //  FUNCTION: BrowserWndProc(HWND, unsigned, WORD, LONG)
00779 //
00780 //  PURPOSE:  Processes messages for the browser container window.
00781 //
00782 LRESULT CALLBACK BrowserWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
00783 {
00784     nsIWebBrowserChrome *chrome = (nsIWebBrowserChrome *) GetWindowLong(hWnd, GWL_USERDATA);
00785     switch (message) 
00786     {
00787     case WM_SIZE:
00788         // Resize the embedded browser
00789         ResizeEmbedding(chrome);
00790         return 0;
00791     case WM_ERASEBKGND:
00792         // Reduce flicker by not painting the non-visible background
00793         return 1;
00794     }
00795     return DefWindowProc(hWnd, message, wParam, lParam);
00796 }
00797 
00798 //
00799 //  FUNCTION: StartupProfile()
00800 //
00801 //  PURPOSE: 
00802 //
00803 nsresult StartupProfile()
00804 {
00805 
00806        nsCOMPtr<nsIFile> appDataDir;
00807        nsresult rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(appDataDir));
00808        if (NS_FAILED(rv))
00809       return rv;
00810     
00811        appDataDir->Append(NS_LITERAL_STRING("winembed"));
00812        nsCOMPtr<nsILocalFile> localAppDataDir(do_QueryInterface(appDataDir));
00813 
00814        nsCOMPtr<nsProfileDirServiceProvider> locProvider;
00815     NS_NewProfileDirServiceProvider(PR_TRUE, getter_AddRefs(locProvider));
00816     if (!locProvider)
00817       return NS_ERROR_FAILURE;
00818     
00819        rv = locProvider->Register();
00820     if (NS_FAILED(rv))
00821       return rv;
00822     
00823        return locProvider->SetProfileDir(localAppDataDir);
00824 
00825 }
00826 
00827 
00829 // WebBrowserChromeUI
00830 
00831 //
00832 //  FUNCTION: CreateNativeWindow()
00833 //
00834 //  PURPOSE: Creates a new browser dialog.
00835 //
00836 //  COMMENTS:
00837 //
00838 //    This function loads the browser dialog from a resource template
00839 //    and returns the HWND for the webbrowser container dialog item
00840 //    to the caller.
00841 //
00842 nativeWindow WebBrowserChromeUI::CreateNativeWindow(nsIWebBrowserChrome* chrome)
00843 {
00844   // Load the browser dialog from resource
00845   HWND hwndDialog;
00846   PRUint32 chromeFlags;
00847 
00848   chrome->GetChromeFlags(&chromeFlags);
00849   if ((chromeFlags & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL)
00850     hwndDialog = CreateDialog(ghInstanceResources,
00851                               MAKEINTRESOURCE(IDD_BROWSER),
00852                               NULL,
00853                               BrowserDlgProc);
00854   else
00855     hwndDialog = CreateDialog(ghInstanceResources,
00856                               MAKEINTRESOURCE(IDD_BROWSER_NC),
00857                               NULL,
00858                               BrowserDlgProc);
00859   if (!hwndDialog)
00860     return NULL;
00861 
00862   // Stick a menu onto it
00863   if (chromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR) {
00864     HMENU hmenuDlg = LoadMenu(ghInstanceResources, MAKEINTRESOURCE(IDC_WINEMBED));
00865     SetMenu(hwndDialog, hmenuDlg);
00866   } else
00867     SetMenu(hwndDialog, 0);
00868 
00869   // Add some interesting URLs to the address drop down
00870   HWND hwndAddress = GetDlgItem(hwndDialog, IDC_ADDRESS);
00871   if (hwndAddress) {
00872     for (int i = 0; i < sizeof(gDefaultURLs) / sizeof(gDefaultURLs[0]); i++)
00873     {
00874       SendMessage(hwndAddress, CB_ADDSTRING, 0, (LPARAM) gDefaultURLs[i]);
00875     }
00876   }
00877 
00878   // Fetch the browser window handle
00879   HWND hwndBrowser = GetDlgItem(hwndDialog, IDC_BROWSER);
00880   SetWindowLong(hwndBrowser, GWL_USERDATA, (LONG)chrome);  // save the browser LONG_PTR.
00881   SetWindowLong(hwndBrowser, GWL_STYLE, GetWindowLong(hwndBrowser, GWL_STYLE) | WS_CLIPCHILDREN);
00882 
00883   // Activate the window
00884   PostMessage(hwndDialog, WM_ACTIVATE, WA_ACTIVE, 0);
00885 
00886   gDialogCount++;
00887 
00888   return hwndBrowser;
00889 }
00890 
00891 
00892 //
00893 // FUNCTION: Destroy()
00894 //
00895 // PURPOSE: Destroy the window specified by the chrome
00896 //
00897 void WebBrowserChromeUI::Destroy(nsIWebBrowserChrome* chrome)
00898 {
00899   nsCOMPtr<nsIWebBrowser> webBrowser;
00900   nsCOMPtr<nsIWebNavigation> webNavigation;
00901 
00902   chrome->GetWebBrowser(getter_AddRefs(webBrowser));
00903   webNavigation = do_QueryInterface(webBrowser);
00904   if (webNavigation)
00905     webNavigation->Stop(nsIWebNavigation::STOP_ALL);
00906 
00907   chrome->ExitModalEventLoop(NS_OK);
00908 
00909   HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
00910   if (hwndDlg == NULL)
00911     return;
00912 
00913   // Explicitly destroy the embedded browser and then the chrome
00914 
00915   // First the browser
00916   nsCOMPtr<nsIWebBrowser> browser = nsnull;
00917   chrome->GetWebBrowser(getter_AddRefs(browser));
00918   nsCOMPtr<nsIBaseWindow> browserAsWin = do_QueryInterface(browser);
00919   if (browserAsWin)
00920     browserAsWin->Destroy();
00921 
00922       // Now the chrome
00923   chrome->SetWebBrowser(nsnull);
00924   NS_RELEASE(chrome);
00925 }
00926 
00927 
00928 //
00929 // FUNCTION: Called as the final act of a chrome object during its destructor
00930 //
00931 void WebBrowserChromeUI::Destroyed(nsIWebBrowserChrome* chrome)
00932 {
00933     HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
00934     if (hwndDlg == NULL)
00935     {
00936         return;
00937     }
00938 
00939     // Clear the window user data
00940     HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
00941     SetWindowLong(hwndBrowser, GWL_USERDATA, nsnull);
00942     DestroyWindow(hwndBrowser);
00943     DestroyWindow(hwndDlg);
00944 
00945     --gDialogCount;
00946     if (gDialogCount == 0)
00947     {
00948         // Quit when there are no more browser objects
00949         PostQuitMessage(0);
00950     }
00951 }
00952 
00953 
00954 //
00955 // FUNCTION: Set the input focus onto the browser window
00956 //
00957 void WebBrowserChromeUI::SetFocus(nsIWebBrowserChrome *chrome)
00958 {
00959     HWND hwndDlg = GetBrowserDlgFromChrome(chrome);
00960     if (hwndDlg == NULL)
00961     {
00962         return;
00963     }
00964     
00965     HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER);
00966     ::SetFocus(hwndBrowser);
00967 }
00968 
00969 //
00970 //  FUNCTION: UpdateStatusBarText()
00971 //
00972 //  PURPOSE: Set the status bar text.
00973 //
00974 void WebBrowserChromeUI::UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const PRUnichar* aStatusText)
00975 {
00976     HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
00977     nsCString status; 
00978     if (aStatusText)
00979         status.AssignWithConversion(aStatusText);
00980     SetDlgItemText(hwndDlg, IDC_STATUS, status.get());
00981 }
00982 
00983 
00984 //
00985 //  FUNCTION: UpdateCurrentURI()
00986 //
00987 //  PURPOSE: Updates the URL address field
00988 //
00989 void WebBrowserChromeUI::UpdateCurrentURI(nsIWebBrowserChrome *aChrome)
00990 {
00991     nsCOMPtr<nsIWebBrowser> webBrowser;
00992     nsCOMPtr<nsIWebNavigation> webNavigation;
00993     aChrome->GetWebBrowser(getter_AddRefs(webBrowser));
00994     webNavigation = do_QueryInterface(webBrowser);
00995 
00996     nsCOMPtr<nsIURI> currentURI;
00997     webNavigation->GetCurrentURI(getter_AddRefs(currentURI));
00998     if (currentURI)
00999     {
01000         nsCAutoString uriString;
01001         currentURI->GetAsciiSpec(uriString);
01002         HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
01003         SetDlgItemText(hwndDlg, IDC_ADDRESS, uriString.get());
01004     }
01005 }
01006 
01007 
01008 //
01009 //  FUNCTION: UpdateBusyState()
01010 //
01011 //  PURPOSE: Refreshes the stop/go buttons in the browser dialog
01012 //
01013 void WebBrowserChromeUI::UpdateBusyState(nsIWebBrowserChrome *aChrome, PRBool aBusy)
01014 {
01015     HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
01016     HWND button;
01017     button = GetDlgItem(hwndDlg, IDC_STOP);
01018     if (button)
01019         EnableWindow(button, aBusy);
01020     button = GetDlgItem(hwndDlg, IDC_GO);
01021     if (button)
01022         EnableWindow(button, !aBusy);
01023     UpdateUI(aChrome);
01024 }
01025 
01026 
01027 //
01028 //  FUNCTION: UpdateProgress()
01029 //
01030 //  PURPOSE: Refreshes the progress bar in the browser dialog
01031 //
01032 void WebBrowserChromeUI::UpdateProgress(nsIWebBrowserChrome *aChrome, PRInt32 aCurrent, PRInt32 aMax)
01033 {
01034     HWND hwndDlg = GetBrowserDlgFromChrome(aChrome);
01035     HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS);
01036     if (aCurrent < 0)
01037     {
01038         aCurrent = 0;
01039     }
01040     if (aCurrent > aMax)
01041     {
01042         aMax = aCurrent + 20; // What to do?
01043     }
01044     if (hwndProgress)
01045     {
01046         SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, aMax));
01047         SendMessage(hwndProgress, PBM_SETPOS, aCurrent, 0);
01048     }
01049 }
01050 
01051 //
01052 //  FUNCTION: ShowContextMenu()
01053 //
01054 //  PURPOSE: Display a context menu for the given node
01055 //
01056 void WebBrowserChromeUI::ShowContextMenu(nsIWebBrowserChrome *aChrome, PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
01057 {
01058     // TODO code to test context flags and display a popup menu should go here
01059 }
01060 
01061 //
01062 //  FUNCTION: ShowTooltip()
01063 //
01064 //  PURPOSE: Show a tooltip
01065 //
01066 void WebBrowserChromeUI::ShowTooltip(nsIWebBrowserChrome *aChrome, PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText)
01067 {
01068     // TODO code to show a tooltip should go here
01069 }
01070 
01071 //
01072 //  FUNCTION: HideTooltip()
01073 //
01074 //  PURPOSE: Hide the tooltip
01075 //
01076 void WebBrowserChromeUI::HideTooltip(nsIWebBrowserChrome *aChrome)
01077 {
01078     // TODO code to hide a tooltip should go here
01079 }
01080 
01081 void WebBrowserChromeUI::ShowWindow(nsIWebBrowserChrome *aChrome, PRBool aShow)
01082 {
01083   HWND win = GetBrowserDlgFromChrome(aChrome);
01084   ::ShowWindow(win, aShow ? SW_RESTORE : SW_HIDE);
01085 }
01086 
01087 void WebBrowserChromeUI::SizeTo(nsIWebBrowserChrome *aChrome, PRInt32 aWidth, PRInt32 aHeight)
01088 {
01089   HWND hchrome = GetBrowserDlgFromChrome(aChrome);
01090   HWND hbrowser = GetBrowserFromChrome(aChrome);
01091   RECT chromeRect, browserRect;
01092 
01093   ::GetWindowRect(hchrome,  &chromeRect);
01094   ::GetWindowRect(hbrowser, &browserRect);
01095 
01096   PRInt32 decoration_x = (browserRect.left - chromeRect.left) + 
01097                          (chromeRect.right - browserRect.right);
01098   PRInt32 decoration_y = (browserRect.top - chromeRect.top) + 
01099                          (chromeRect.bottom - browserRect.bottom);
01100 
01101   ::MoveWindow(hchrome, chromeRect.left, chromeRect.top,
01102       aWidth+decoration_x,
01103       aHeight+decoration_y, TRUE);
01104 }
01105 
01106 //
01107 //  FUNCTION: GetResourceStringByID()
01108 //
01109 //  PURPOSE: Get the resource string for the ID
01110 //
01111 void WebBrowserChromeUI::GetResourceStringById(PRInt32 aID, char ** aReturn)
01112 {
01113     char resBuf[MAX_LOADSTRING];
01114     int retval = LoadString( ghInstanceResources, aID, (LPTSTR)resBuf, sizeof(resBuf) );
01115     if (retval != 0)
01116     {
01117         int resLen = strlen(resBuf);
01118         *aReturn = (char *)calloc(resLen+1, sizeof(char *));
01119         if (!*aReturn) return;
01120             PL_strncpy(*aReturn, (char *) resBuf, resLen);
01121     }
01122     return;
01123 }
01124 
01125 //-----------------------------------------------------------------------------
01126 // AppCallbacks
01127 //-----------------------------------------------------------------------------
01128 
01129 nsresult AppCallbacks::CreateBrowserWindow(PRUint32 aChromeFlags,
01130            nsIWebBrowserChrome *aParent,
01131            nsIWebBrowserChrome **aNewWindow)
01132 {
01133   WebBrowserChrome * chrome = new WebBrowserChrome();
01134   if (!chrome)
01135     return NS_ERROR_FAILURE;
01136 
01137   // the interface to return and one addref, which we assume will be
01138   // immediately released
01139   CallQueryInterface(NS_STATIC_CAST(nsIWebBrowserChrome*, chrome), aNewWindow);
01140   // now an extra addref; the window owns itself (to be released by
01141   // WebBrowserChromeUI::Destroy)
01142   NS_ADDREF(*aNewWindow);
01143 
01144   chrome->SetChromeFlags(aChromeFlags);
01145   chrome->SetParent(aParent);
01146 
01147   // Insert the browser
01148   nsCOMPtr<nsIWebBrowser> newBrowser;
01149   chrome->CreateBrowser(-1, -1, -1, -1, getter_AddRefs(newBrowser));
01150   if (!newBrowser)
01151     return NS_ERROR_FAILURE;
01152 
01153   // Place it where we want it.
01154   ResizeEmbedding(NS_STATIC_CAST(nsIWebBrowserChrome*, chrome));
01155 
01156   // if opened as chrome, it'll be made visible after the chrome has loaded.
01157   // otherwise, go ahead and show it now.
01158   if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME))
01159     WebBrowserChromeUI::ShowWindow(*aNewWindow, PR_TRUE);
01160 
01161   return NS_OK;
01162 }
01163 
01164 void AppCallbacks::EnableChromeWindow(nsIWebBrowserChrome *aWindow,
01165                       PRBool aEnabled)
01166 {
01167   HWND hwnd = GetBrowserDlgFromChrome(aWindow);
01168   ::EnableWindow(hwnd, aEnabled ? TRUE : FALSE);
01169 }
01170 
01171 PRUint32 AppCallbacks::RunEventLoop(PRBool &aRunCondition)
01172 {
01173   MSG msg;
01174   HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
01175 
01176   while (aRunCondition ) {
01177     // Process pending messages
01178     while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
01179       if (!::GetMessage(&msg, NULL, 0, 0)) {
01180         // WM_QUIT
01181         aRunCondition = PR_FALSE;
01182         break;
01183       }
01184 
01185       PRBool wasHandled = PR_FALSE;
01186       ::NS_HandleEmbeddingEvent(msg, wasHandled);
01187       if (wasHandled)
01188         continue;
01189 
01190       ::TranslateMessage(&msg);
01191       ::DispatchMessage(&msg);
01192     }
01193 
01194     // Do idle stuff
01195     ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 100, QS_ALLEVENTS);
01196   }
01197   ::CloseHandle(hFakeEvent);
01198   return msg.wParam;
01199 }