/*++ Copyright (c) 1996 Microsoft Corporation Module Name: WizList.cpp : implementation file File History: JonY Jan-96 created --*/ #include "stdafx.h" #include "Mustard.h" #include "WizList.h" #include "Listdata.h" #include "startd.h" #include #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif const USHORT BITMAP_WIDTH = 32; const USHORT BITMAP_HEIGHT = 32; const USHORT MAX_PRINTER_NAME = 256 + 2; const USHORT CELL_HEIGHT = 71; const USHORT CELL_WIDTH = 300; typedef BOOL (*BPRINTERSETUP)(HWND, UINT, UINT, LPTSTR, UINT*, LPCTSTR); ///////////////////////////////////////////////////////////////////////////// // CWizList CWizList::CWizList() { CString fontname; fontname.LoadString(IDS_FONT_NAME); CString fontheight; fontheight.LoadString(IDS_FONT_SIZE); // regular font m_pFont = new CFont; LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); // Clear out structure. lf.lfHeight = (LONG)_tcstoul(fontheight, NULL, 10); _tcscpy(lf.lfFaceName, fontname); lf.lfWeight = 100; m_pFont->CreateFontIndirect(&lf); // Create the font. // bold font m_pFontBold = new CFont; memset(&lf, 0, sizeof(LOGFONT)); // Clear out structure. lf.lfHeight = (LONG)_tcstoul(fontheight, NULL, 10); _tcscpy(lf.lfFaceName, fontname); lf.lfWeight = 700; m_pFontBold->CreateFontIndirect(&lf); // Create the font. m_hPrinterLib = NULL; } CWizList::~CWizList() { if (m_pFont != NULL) delete m_pFont; if (m_pFontBold != NULL) delete m_pFontBold; if (m_hPrinterLib != NULL) FreeLibrary(m_hPrinterLib); } BEGIN_MESSAGE_MAP(CWizList, CListBox) //{{AFX_MSG_MAP(CWizList) ON_WM_MOUSEMOVE() ON_WM_LBUTTONDOWN() ON_CONTROL_REFLECT(LBN_SETFOCUS, OnSetfocus) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CWizList message handlers void CWizList::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { COLORREF crefOldText; CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); pDC->SetBkMode(OPAQUE); // save the current font for later CFont* pOldFont = (CFont*)pDC->SelectObject(m_pFont); CItemData* pData = (CItemData*)GetItemData(lpDrawItemStruct->itemID); LPCTSTR pName2 = (const TCHAR*)pData->csDesc; LPCTSTR pName = (const TCHAR*)pData->csName; HICON hIcon = pData->hIcon; HICON hSelIcon = pData->hSelIcon; int nTop = (lpDrawItemStruct->rcItem.bottom + lpDrawItemStruct->rcItem.top) / 2; switch (lpDrawItemStruct->itemAction) { case ODA_SELECT: case ODA_DRAWENTIRE: // paint the left side - then draw text CRect crRight(50, lpDrawItemStruct->rcItem.top, lpDrawItemStruct->rcItem.right, lpDrawItemStruct->rcItem.bottom); CBrush* pBrush = new CBrush; pBrush->CreateSolidBrush(GetSysColor(COLOR_WINDOW)); pDC->FillRect(crRight, pBrush); // paint the right - then draw text pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); crRight = CRect(lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top, 50, lpDrawItemStruct->rcItem.bottom); pDC->FillRect(crRight, pBrush); crRight = CRect(lpDrawItemStruct->rcItem.left + 5, lpDrawItemStruct->rcItem.top + 3, 140, lpDrawItemStruct->rcItem.bottom); // Is the item selected? if (lpDrawItemStruct->itemState & ODS_SELECTED) { // Display bitmap nTop = (lpDrawItemStruct->rcItem.bottom + lpDrawItemStruct->rcItem.top - BITMAP_HEIGHT) / 2; pDC->DrawIcon(lpDrawItemStruct->rcItem.left + 9, nTop - 9, hSelIcon); // paint the right - then draw text crefOldText = pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)); pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT)); } else { // Display bitmap nTop = (lpDrawItemStruct->rcItem.bottom + lpDrawItemStruct->rcItem.top - BITMAP_HEIGHT) / 2; pDC->DrawIcon(lpDrawItemStruct->rcItem.left + 9, nTop - 9, hIcon); crefOldText = pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); pDC->SetBkColor(GetSysColor(COLOR_WINDOW)); } // draw the top (bold) text pDC->SelectObject(m_pFontBold); CRect crTop = CRect(60, lpDrawItemStruct->rcItem.top + 8, lpDrawItemStruct->rcItem.right - 10, lpDrawItemStruct->rcItem.bottom); pDC->DrawText(pName, _tcslen(pName), crTop, DT_WORDBREAK); // draw the lower text pDC->SelectObject(m_pFont); CRect crBottom = CRect(60, lpDrawItemStruct->rcItem.top + 28, lpDrawItemStruct->rcItem.right - 10, lpDrawItemStruct->rcItem.bottom); pDC->DrawText(pName2, _tcslen(pName2), crBottom, DT_WORDBREAK); pDC->SelectObject(pOldFont); pDC->SetTextColor(crefOldText ); delete pBrush; break; } // Restore the original font pDC->SelectObject(pOldFont); } void CWizList::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { lpMeasureItemStruct->itemHeight = CELL_HEIGHT; lpMeasureItemStruct->itemWidth = CELL_WIDTH; } void CWizList::OnMouseMove(UINT nFlags, CPoint point) { if (((CStartD*)GetParent())->IsActive()) { USHORT y = (USHORT)(point.y / CELL_HEIGHT); USHORT usCurSel = (USHORT)GetCurSel(); if (usCurSel != y) SetCurSel(y); // tell the other guy not to show any selection m_pOtherGuy->SetCurSel(-1); } CListBox::OnMouseMove(nFlags, point); } void CWizList::OnLButtonDown(UINT nFlags, CPoint point) { USHORT usCurSel = (USHORT)GetCurSel(); // Exit if there's no selection. if (usCurSel == (USHORT)-1) return; CItemData* pData = (CItemData*)GetItemData(usCurSel); // is this the printer wiz? if (pData->csAppStart1 == "") { try { LaunchPrinterWizard(); } catch (...) { TRACE(_T("An exception occurred while attempting to start the Add Printer Wizard.\n")); } } else { // otherwise CString csCmdLine = pData->csAppStart1 + " "; csCmdLine += pData->csAppStart2; TCHAR* pCmdLine = csCmdLine.GetBuffer(csCmdLine.GetLength()); STARTUPINFO sInfo; ZeroMemory(&sInfo, sizeof(sInfo)); sInfo.cb = sizeof(sInfo); PROCESS_INFORMATION pInfo; BOOL bProc = CreateProcess(NULL, pCmdLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sInfo, &pInfo); if (!bProc) AfxMessageBox(IDS_NO_START); csCmdLine.ReleaseBuffer(); } // CListBox::OnLButtonDown(nFlags, point); } void CWizList::PumpMessages() { MSG msg; // check outstanding messages while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (!IsDialogMessage(&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } BOOL CWizList::LaunchPrinterWizard() { CWaitCursor wc; BOOL bReturn = TRUE; HRESULT hr; LPSHELLFOLDER pshf, pshfPrinters; LPITEMIDLIST pidlPrintFolder, pidlPrintObj; LPMALLOC pMalloc; // Get a pointer to the shell's IMalloc interface. hr = SHGetMalloc(&pMalloc); if (SUCCEEDED(hr)) { // Get a pointer to the shell's IShellFolder interface. hr = SHGetDesktopFolder(&pshf); if (SUCCEEDED(hr)) { // Get a PIDL for the Printers folder. hr = SHGetSpecialFolderLocation(GetSafeHwnd(), CSIDL_PRINTERS, &pidlPrintFolder); if (SUCCEEDED(hr)) { // Get a pointer to the IShellFolder interface for the Printer folder. hr = pshf->BindToObject(pidlPrintFolder, NULL, IID_IShellFolder, (LPVOID*)&pshfPrinters); if (SUCCEEDED(hr)) { // Get a PIDL for the Add Printer object in the Printers folder. hr = GetAddPrinterObject(pshfPrinters, &pidlPrintObj); if (SUCCEEDED(hr)) { LPCONTEXTMENU pcm; // Get a pointer to the Printer folder's IContextMenu interface. hr = pshfPrinters->GetUIObjectOf(GetSafeHwnd(), 1, (LPCITEMIDLIST*)&pidlPrintObj, IID_IContextMenu, NULL, (LPVOID*)&pcm); if (SUCCEEDED(hr)) { // Create a popup menu to hold the items in the context menu. HMENU hMenu = CreatePopupMenu(); if (hMenu != NULL) { // Fill the menu. hr = pcm->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE); if (SUCCEEDED(hr)) { CString strCmd(CMDSTR_NEWFOLDER); CHAR szCmd[MAX_PATH + 1]; int i, nCmd, nItems = ::GetMenuItemCount(hMenu); for (i = 0; i < nItems; i++) { // Search through the menu to find the language-independent // identifier for the Add Printer object's Open command. nCmd = GetMenuItemID(hMenu, i); hr = pcm->GetCommandString(i, GCS_VERB, NULL, szCmd, MAX_PATH); TCHAR wStr[255]; memcpy(wStr, szCmd, 255); if (SUCCEEDED(hr) && strCmd == wStr) { CMINVOKECOMMANDINFO cmi; cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); cmi.fMask = 0; cmi.hwnd = GetSafeHwnd(); cmi.lpVerb = (LPSTR)MAKEINTRESOURCE(nCmd - 1); cmi.lpParameters = NULL; cmi.lpDirectory = NULL; cmi.nShow = SW_SHOW; cmi.dwHotKey = 0; cmi.hIcon = NULL; // Invoke the Open command. hr = pcm->InvokeCommand(&cmi); // Exit the loop. break; if (FAILED(hr)) { TRACE(_T("IContextMenu::InvokeCommand failed.\n")); bReturn = FALSE; } } else { TRACE(_T("IContextMenu::GetCommandString failed.\n")); bReturn = FALSE; } } pcm->Release(); } else { TRACE(_T("IShellFolder::GetUIObjectOf failed.\n")); bReturn = FALSE; } // Destroy the temporary menu. if (!DestroyMenu(hMenu)) TRACE(_T("DestroyMenu failed.\n")); } else { TRACE(_T("CreatePopupMenu failed.\n")); bReturn = FALSE; } } // Release the IShellFolder interface for the Printers folder. pshfPrinters->Release(); } // Free the PIDL for the Add Printer object. pMalloc->Free(pidlPrintObj); } else { TRACE(_T("IShellFolder::BindToObject failed.\n")); bReturn = FALSE; } // Free the PIDL for the Printers folder. pMalloc->Free(pidlPrintFolder); } else { TRACE(_T("SHGetSpecialFolderLocation failed.\n")); bReturn = FALSE; } // Release the pointer to the shell's IShellFolder interface. pshf->Release(); } else { TRACE(_T("SHGetDesktopFolder failed.\n")); bReturn = FALSE; } // Release the pointer to the shell's IMalloc interface. pMalloc->Release(); } else { TRACE(_T("SHGetMalloc failed.\n")); bReturn = FALSE; } return bReturn; } HRESULT CWizList::GetAddPrinterObject(LPSHELLFOLDER pshf, LPITEMIDLIST* ppidl) { HRESULT hr; LPENUMIDLIST pEnum; LPMALLOC pMalloc; // Get a pointer to the shell's IMalloc interface. hr = SHGetMalloc(&pMalloc); if (SUCCEEDED(hr)) { // Get a pointer to the folder's IEnumIDList interface. hr = pshf->EnumObjects(GetSafeHwnd(), SHCONTF_NONFOLDERS, &pEnum); if (SUCCEEDED(hr)) { STRRET str; CString strPrintObj, strEnumObj; // Load the display name for the Add Printer object. strPrintObj.LoadString(IDS_ADD_PRINTER); // Enumerate the objects in the Printers folder. while (pEnum->Next(1, ppidl, NULL) == NOERROR) { // Get the display name for the object. hr = pshf->GetDisplayNameOf((LPCITEMIDLIST)*ppidl, SHGDN_INFOLDER, &str); if (SUCCEEDED(hr)) { // Copy the display name to the strEnumObj string. switch (str.uType) { case STRRET_CSTR: strEnumObj = str.cStr; break; case STRRET_OFFSET: char pStr[255]; strcpy(pStr, (LPCSTR)(((UINT_PTR)*ppidl) + str.uOffset)); TCHAR wStr[255]; mbstowcs(wStr, pStr, 255); strEnumObj = wStr; break; case STRRET_WSTR: strEnumObj = str.pOleStr; break; case 0x04: //STRRET_OFFSETW strEnumObj = (LPCTSTR)(((UINT_PTR)*ppidl) + str.uOffset); break; case 0x05: { TCHAR pStr[255]; memcpy(pStr, str.cStr, 255); strEnumObj = pStr; break; } default: strEnumObj.Empty(); } // If we found the correct object, exit the loop. if (strPrintObj == strEnumObj) break; // Free the PIDL returned by IEnumIDList::Next(). pMalloc->Free(*ppidl); if (FAILED(hr)) { TRACE(_T("IMalloc::Free failed.\n")); break; } } else { TRACE(_T("IShellFolder::GetDisplayNameOf failed.\n")); } } // Release the IEnumIDList pointer. pEnum->Release(); } else { TRACE(_T("IShellFolder::EnumObjects failed.\n")); } // Release the IMalloc pointer. pMalloc->Release(); } return hr; } void CWizList::OnSetfocus() { // tell the other guy not to show any selection m_pOtherGuy->SetCurSel(-1); }