// ************************************************************************** // // RunOnce.Cpp // // Microsoft Confidential // Copyright (c) Microsoft Corporation 1992-1993 // All rights reserved // // RunOnce wrapper. This encapsulates all applications that would like // to run the first time we re-boot. It lists these apps for the user // and allows the user to launce the apps (like apple at ease). // // 5 June 1994 FelixA Started // 8 June Felix Defined registry strings and functionality. // Got small buttons displayed, but not working. // 9 June Felix Both big and small buttons. Nice UI. // Got single click app launching. // // 23 June Felix Moving it to a Chicago make thingy not Dolphin // // *************************************************************************/ // #include "iernonce.h" #include "resource.h" #define CXBORDER 3 // globals HDC g_hdcMem = NULL; // Run time can be set for big or small buttons. int g_cxSmIcon = 0; // Icon sizes. SIZE g_SizeTextExt; // Extent of text in buttons. HFONT g_hfont = NULL; HFONT g_hBoldFont = NULL; HBRUSH g_hbrBkGnd = NULL; ARGSINFO g_aiArgs; // prototypes BOOL CreateGlobals(HWND hwndCtl); BOOL RunOnceFill(HWND hWndLB); void ShrinkToFit(HWND hWnd, HWND hLb); DWORD RunAppsInList(LPVOID lp); LRESULT HandleLBMeasureItem(HWND hwndLB, MEASUREITEMSTRUCT *lpmi); LRESULT HandleLBDrawItem(HWND hwndLB, DRAWITEMSTRUCT *lpdi); void DestroyGlobals(void); INT_PTR CALLBACK DlgProcRunOnceEx(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HANDLE s_hThread = NULL; DWORD dwThread; switch (uMsg) { case WM_INITDIALOG: g_aiArgs = *((ARGSINFO *) lParam); CreateGlobals(hWnd); SetWindowPos(hWnd, NULL, 32, 32, 0, 0, SWP_NOSIZE | SWP_NOZORDER); RunOnceFill(GetDlgItem(hWnd, IDC_LIST2)); // Now calculate the size needed for the LB and resize LB and parent. ShrinkToFit(hWnd, GetDlgItem(hWnd, IDC_LIST2)); if ((s_hThread = CreateThread(NULL, 0, RunAppsInList, (LPVOID) GetDlgItem(hWnd, IDC_LIST2), 0, &dwThread)) == NULL) PostMessage(hWnd, WM_FINISHED, 0, 0L); break; case WM_SETCURSOR: if (g_aiArgs.dwFlags & RRA_WAIT) SetCursor(LoadCursor(NULL, IDC_WAIT)); return TRUE; case WM_MEASUREITEM: if (((MEASUREITEMSTRUCT *) lParam)->CtlType == ODT_LISTBOX) return HandleLBMeasureItem(hWnd, (MEASUREITEMSTRUCT *) lParam); else return FALSE; case WM_DRAWITEM: if (((DRAWITEMSTRUCT *) lParam)->CtlType == ODT_LISTBOX) return HandleLBDrawItem(hWnd, (DRAWITEMSTRUCT *) lParam); else return FALSE; case WM_CTLCOLORLISTBOX: SetTextColor((HDC) wParam, GetSysColor(COLOR_BTNTEXT)); SetBkColor((HDC) wParam, GetSysColor(COLOR_BTNFACE)); return (LRESULT) g_hbrBkGnd; case WM_FINISHED: if (s_hThread != NULL) { while (MsgWaitForMultipleObjects(1, &s_hThread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0) { MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } CloseHandle(s_hThread); s_hThread = NULL; } DestroyGlobals(); EndDialog(hWnd, 0); break; default: return FALSE; } return TRUE; } LPSTR MakeAnsiStrFromWide(LPWSTR pwsz) { LPSTR psz; int i; // arg checking. // if (!pwsz) return NULL; // compute the length // i = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, NULL, 0, NULL, NULL); if (i <= 0) return NULL; psz = (LPSTR) CoTaskMemAlloc(i * sizeof(CHAR)); if (!psz) return NULL; WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, i, NULL, NULL); psz[i - 1] = 0; return psz; } BOOL CreateGlobals(HWND hwndCtl) { LOGFONT lf; HDC hdc; HFONT hfontOld; g_cxSmIcon = GetSystemMetrics(SM_CXSMICON); g_hbrBkGnd = CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); if ((hfontOld = (HFONT) (WORD) SendMessage(hwndCtl, WM_GETFONT, 0, 0L)) != NULL) { if (GetObject(hfontOld, sizeof(LOGFONT), (LPSTR) &lf)) { // The CreateFontIndirect calls in IESetup Wzd works correctly on // all platforms... and they convert the Font name to Ansi // Hence to solve the Thai NT/Thai Win9x problem, we also convert // the font name to Ansi before calling CreateFontIndirect. // #58923: Now the FaceName returned by GetObject is not UNICODE on all // platforms. On Win9x, it is Ansi and this screws up things when // we call MakeAnsiStrFromWide on it. Hence to avoid problems, check // if returned FaceName is Wide if (lf.lfFaceName[1] == '\0') { LPSTR pszAnsiName; pszAnsiName = MakeAnsiStrFromWide((unsigned short *)lf.lfFaceName); lstrcpy((char *)lf.lfFaceName, pszAnsiName); CoTaskMemFree((LPVOID)pszAnsiName); } lf.lfWeight = 400; g_hfont = CreateFontIndirect(&lf); lf.lfWeight = 700; g_hBoldFont = CreateFontIndirect(&lf); } } if (g_hfont) { TCHAR *szLotsaWs = TEXT("WWWWWWWWWW"); // Calc sensible size for text in buttons. hdc = GetDC(NULL); hfontOld = (HFONT) SelectObject(hdc, g_hfont); GetTextExtentPoint(hdc, szLotsaWs, lstrlen(szLotsaWs), &g_SizeTextExt); SelectObject(hdc, hfontOld); ReleaseDC(NULL, hdc); return TRUE; } return FALSE; } //*************************************************************************** // // RunOnceFill() // Fills the List box in the run-once dlg. // // ENTRY: // HWND of the thing to fill. // // EXIT: // // //*************************************************************************** BOOL RunOnceFill(HWND hWndLB) { RunOnceExSection *pCurrentRunOnceExSection; int iSectionIndex; // if Title value is present, display it if (*g_szTitleString) SetWindowText(GetParent(hWndLB), g_szTitleString); for (iSectionIndex = 0; iSectionIndex < g_aiArgs.iNumberOfSections; iSectionIndex++) { pCurrentRunOnceExSection = (RunOnceExSection *) DPA_GetPtr(g_aiArgs.hdpaSections, iSectionIndex); if (*pCurrentRunOnceExSection->m_szDisplayName != TEXT('\0')) SendMessage(hWndLB, LB_ADDSTRING, 0, (LPARAM) pCurrentRunOnceExSection->m_szDisplayName); } return TRUE; } //*************************************************************************** // // ShrinkToFit() // Makes the List box no bigger then it has to be // makes the parent window rsize to the LB size. // // ENTRY: // hwnd Parent // hwnd List box // // EXIT: // //*************************************************************************** void ShrinkToFit(HWND hWnd, HWND hLb) { LONG lCount; LONG lNumItems; LONG lTotalHeight; LONG lHeight; RECT rWnd; LONG lChange; lTotalHeight = 0; lNumItems = (LONG)SendMessage(hLb, LB_GETCOUNT, 0, 0L); for (lCount = 0; lCount < lNumItems; lCount++) { lHeight = (LONG)SendMessage(hLb, LB_GETITEMHEIGHT, lCount, 0L); lTotalHeight += lHeight; } // Set the height of the ListBox to the number of items in it. GetWindowRect(hLb, &rWnd); SetWindowPos(hLb, hWnd, 0, 0, rWnd.right - rWnd.left - (CXBORDER * 2 + g_cxSmIcon), lTotalHeight, SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER); // Work out how much it changed in height lChange = lTotalHeight - (rWnd.bottom - rWnd.top); // Size the parent to fit around the child. GetWindowRect(hWnd, &rWnd); SetWindowPos(hWnd, 0, 0, 0, rWnd.right - rWnd.left, rWnd.bottom - rWnd.top + lChange, SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER); } //*************************************************************************** // // RunAppsInList() // Enumerates all the items in the list box, spawning each in turn. // // ENTRY: // HWND of Parent. // // EXIT: // // //*************************************************************************** DWORD RunAppsInList(LPVOID lp) { ProcessSections(g_aiArgs.hkeyParent, g_aiArgs.pszSubkey, g_aiArgs.dwFlags, g_aiArgs.hdpaSections, g_aiArgs.iNumberOfSections, (HWND) lp); // terminate the dialog box PostMessage(GetParent((HWND) lp), WM_FINISHED, 0, 0L); return 0; } LRESULT HandleLBMeasureItem(HWND hDlg, MEASUREITEMSTRUCT *lpmi) { RECT rWnd; int wWnd; HDC hDC; HFONT hfontOld; TCHAR szText[MAX_ENTRYNAME]; // Get the Height and Width of the child window GetWindowRect(hDlg, &rWnd); wWnd = rWnd.right - rWnd.left; lpmi->itemWidth = wWnd; hDC = GetDC(NULL); if ((hfontOld = (HFONT) SelectObject(hDC, g_hBoldFont)) != 0) { rWnd.top = 0; rWnd.left = CXBORDER * 2 + g_cxSmIcon; rWnd.right = lpmi->itemWidth - rWnd.left - CXBORDER * 2 - g_cxSmIcon; rWnd.bottom = 0; *szText = TEXT('\0'); SendMessage(GetDlgItem(hDlg, IDC_LIST2), LB_GETTEXT, (WPARAM) lpmi->itemID, (LPARAM) szText); DrawText(hDC, szText, lstrlen(szText), &rWnd, DT_CALCRECT | DT_WORDBREAK); SelectObject(hDC, hfontOld); } ReleaseDC(NULL, hDC); lpmi->itemHeight = rWnd.bottom + CXBORDER * 2; return TRUE; } //*************************************************************************** // // HandleLBDrawItem() // Draws the Title, Text, and icon for an entry. // // ENTRY: // HWND and the Item to draw. // // EXIT: // // //*************************************************************************** LRESULT HandleLBDrawItem(HWND hDlg, DRAWITEMSTRUCT *lpdi) { RECT rc; HFONT hfontOld; int xArrow,y; BITMAP bm; HGDIOBJ hbmArrow, hbmOld; TCHAR szText[MAX_ENTRYNAME]; // Don't draw anything for an empty list. if ((int) lpdi->itemID < 0) return TRUE; if ((lpdi->itemAction & ODA_SELECT) || (lpdi->itemAction & ODA_DRAWENTIRE)) { // Put in the Title text hfontOld = (HFONT) SelectObject(lpdi->hDC, (lpdi->itemState & ODS_SELECTED) ? g_hBoldFont : g_hfont); ExtTextOut(lpdi->hDC, lpdi->rcItem.left + CXBORDER * 2 + g_cxSmIcon, lpdi->rcItem.top + CXBORDER, ETO_OPAQUE, &lpdi->rcItem, NULL, 0, NULL); rc.top = lpdi->rcItem.top + CXBORDER; rc.left = lpdi->rcItem.left + CXBORDER * 2 + g_cxSmIcon; rc.right = lpdi->rcItem.right; rc.bottom = lpdi->rcItem.bottom; *szText = TEXT('\0'); SendMessage(GetDlgItem(hDlg, IDC_LIST2), LB_GETTEXT, (WPARAM) lpdi->itemID, (LPARAM) szText); DrawText(lpdi->hDC, szText, lstrlen(szText), &rc, DT_WORDBREAK); SelectObject(lpdi->hDC, hfontOld); // Draw the little triangle thingies. if (lpdi->itemState & ODS_SELECTED) { if (!g_hdcMem) { g_hdcMem = CreateCompatibleDC(lpdi->hDC); } if (g_hdcMem) { hbmArrow = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW)); GetObject(hbmArrow, sizeof(bm), &bm); hbmOld = SelectObject(g_hdcMem, hbmArrow); xArrow = lpdi->rcItem.left + CXBORDER; y = ((g_SizeTextExt.cy - bm.bmHeight) / 2) + CXBORDER + lpdi->rcItem.top; BitBlt(lpdi->hDC, xArrow, y, bm.bmWidth, bm.bmHeight, g_hdcMem, 0, 0, SRCAND); SelectObject(g_hdcMem, hbmOld); DeleteObject(hbmArrow); } } } return TRUE; } void DestroyGlobals(void) { if (g_hfont) { DeleteObject(g_hfont); g_hfont = NULL; } if (g_hBoldFont) { DeleteObject(g_hBoldFont); g_hBoldFont = NULL; } if (g_hbrBkGnd) { DeleteObject(g_hbrBkGnd); g_hbrBkGnd = NULL; } }