home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2006 April / DPPRO0406DVD.ISO / Essentials / Programming / Notepad2 / Source / NP2SRC.ZIP / Helpers.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-06-25  |  31.0 KB  |  1,283 lines

  1. /******************************************************************************
  2. *
  3. *
  4. * Notepad2
  5. *
  6. * Helpers.c
  7. *   General helper functions
  8. *
  9. * See Readme.txt for more information about this source code.
  10. * Please send me your comments to this work.
  11. *
  12. * Distributed under the terms of the GNU General Public License,
  13. * see License.txt for details.
  14. *
  15. *                                              (c) Florian Balmer 1996-2004
  16. *                                                       textview@bluewin.ch
  17. *                                               http://www.flos-freeware.ch
  18. *
  19. *
  20. ******************************************************************************/
  21. #include <windows.h>
  22. #include <shlobj.h>
  23. #include <shlwapi.h>
  24. #include <commctrl.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "appreg.h"
  28. #include "helpers.h"
  29. #include "resource.h"
  30.  
  31.  
  32.  
  33. //=============================================================================
  34. //
  35. //  BeginWaitCursor()
  36. //
  37. void BeginWaitCursor()
  38. {
  39.  
  40.   DestroyCursor(
  41.     SetCursor(
  42.     LoadCursor(NULL,IDC_WAIT)));
  43.  
  44. }
  45.  
  46.  
  47. //=============================================================================
  48. //
  49. //  EndWaitCursor()
  50. //
  51. void EndWaitCursor()
  52. {
  53.  
  54.   DestroyCursor(
  55.     SetCursor(
  56.     LoadCursor(NULL,IDC_ARROW)));
  57.  
  58. }
  59.  
  60.  
  61. //=============================================================================
  62. //
  63. //  KeepWindowsAlive()
  64. //
  65. /*void KeepWindowsAlive()
  66. {
  67.   MSG msg;
  68.   if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  69.   {
  70.     TranslateMessage(&msg);
  71.     DispatchMessage(&msg);
  72.   }
  73. }*/
  74.  
  75.  
  76. //=============================================================================
  77. //
  78. //  IsWindowsNT()
  79. //
  80. BOOL IsWindowsNT()
  81. {
  82.   OSVERSIONINFO osvi;
  83.   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  84.  
  85.   GetVersionEx(&osvi);
  86.  
  87.   return (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
  88. }
  89.  
  90.  
  91. //=============================================================================
  92. //
  93. //  PrivateIsAppThemed()
  94. //
  95. BOOL PrivateIsAppThemed()
  96. {
  97.   BOOL bIsAppThemed = FALSE;
  98.   HMODULE hDll = LoadLibrary("uxtheme.dll");
  99.   if (hDll)
  100.   {
  101.     FARPROC fp = GetProcAddress(hDll,"IsAppThemed");
  102.     if (fp)
  103.     {
  104.       bIsAppThemed = fp();
  105.     }
  106.     FreeLibrary(hDll);
  107.   }
  108.   return bIsAppThemed;
  109. }
  110.  
  111.  
  112. //=============================================================================
  113. //
  114. //  SetWindowTitle()
  115. //
  116. BOOL SetWindowTitle(HWND hwnd,UINT uIDAppName,UINT uIDUntitled,
  117.                     LPCSTR lpszFile,BOOL bShort,BOOL bModified,
  118.                     UINT uIDReadOnly,BOOL bReadOnly)
  119. {
  120.  
  121.   char szUntitled[128],szAppName[128],szReadOnly[32],szTitle[256];
  122.   static const char *pszSep = " - ";
  123.   static const char *pszMod = "* ";
  124.  
  125.   if (!GetString(uIDAppName,szAppName,COUNTOF(szAppName)) ||
  126.       !GetString(uIDUntitled,szUntitled,COUNTOF(szUntitled)))
  127.     return FALSE;
  128.  
  129.   if (bModified)
  130.     lstrcpy(szTitle,pszMod);
  131.   else
  132.     lstrcpy(szTitle,"");
  133.  
  134.   if (lstrlen(lpszFile))
  135.   {
  136.     if (bShort && !PathIsRoot(lpszFile))
  137.     {
  138.       SHFILEINFO shfi;
  139.       SHGetFileInfo2(lpszFile,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME);
  140.       lstrcat(szTitle,shfi.szDisplayName);
  141.     }
  142.     else
  143.       lstrcat(szTitle,lpszFile);
  144.   }
  145.  
  146.   else
  147.     lstrcat(szTitle,szUntitled);
  148.  
  149.   if (bReadOnly && GetString(uIDReadOnly,szReadOnly,COUNTOF(szReadOnly)))
  150.   {
  151.     lstrcat(szTitle," ");
  152.     lstrcat(szTitle,szReadOnly);
  153.   }
  154.  
  155.   lstrcat(szTitle,pszSep);
  156.   lstrcat(szTitle,szAppName);
  157.  
  158.   return SetWindowText(hwnd,szTitle);
  159.  
  160. }
  161.  
  162.  
  163. //=============================================================================
  164. //
  165. //  SetWindowTransparentMode()
  166. //
  167. void SetWindowTransparentMode(HWND hwnd,BOOL bTransparentMode)
  168. {
  169.   FARPROC fp;
  170.   int  iAlphaPercent;
  171.   BYTE bAlpha;
  172.  
  173.   if (bTransparentMode) {
  174.     if (fp = GetProcAddress(GetModuleHandle("User32"),"SetLayeredWindowAttributes")) {
  175.     SetWindowLong(hwnd,GWL_EXSTYLE,
  176.       GetWindowLong(hwnd,GWL_EXSTYLE) | /*WS_EX_LAYERED*/0x00080000);
  177.  
  178.     // get opacity level from registry
  179.     iAlphaPercent = RegGetAppIntEx("Settings","OpacityLevel",75);
  180.     if (iAlphaPercent < 0 || iAlphaPercent > 100)
  181.       iAlphaPercent = 75;
  182.     bAlpha = 255 / 100 * iAlphaPercent;
  183.  
  184.     fp(hwnd,0,bAlpha,/*LWA_ALPHA*/0x00000002); } }
  185.  
  186.   else
  187.     SetWindowLong(hwnd,GWL_EXSTYLE,
  188.       GetWindowLong(hwnd,GWL_EXSTYLE) & ~/*WS_EX_LAYERED*/0x00080000);
  189. }
  190.  
  191.  
  192. //=============================================================================
  193. //
  194. //  CenterDlgInParent()
  195. //
  196. void CenterDlgInParent(HWND hDlg)
  197. {
  198.  
  199.   RECT rcDlg;
  200.   HWND hParent;
  201.   RECT rcParent;
  202.   RECT rcScreen;
  203.  
  204.   int xMin, yMin, xMax, yMax, x, y;
  205.  
  206.   GetWindowRect(hDlg,&rcDlg);
  207.  
  208.   hParent = GetParent(hDlg);
  209.   GetWindowRect(hParent,&rcParent);
  210.  
  211.   SystemParametersInfo(SPI_GETWORKAREA,0,&rcScreen,0);
  212.  
  213.   xMin = 0;
  214.   yMin = 0;
  215.  
  216.   xMax = (rcScreen.right - rcScreen.left) - (rcDlg.right - rcDlg.left);
  217.   yMax = (rcScreen.bottom - rcScreen.top) - (rcDlg.bottom - rcDlg.top);
  218.  
  219.   if ((rcParent.right - rcParent.left) - (rcDlg.right - rcDlg.left) > 20)
  220.     x = rcParent.left + (((rcParent.right - rcParent.left) - (rcDlg.right - rcDlg.left)) / 2);
  221.   else
  222.     x = rcParent.left + 70;
  223.  
  224.   if ((rcParent.bottom - rcParent.top) - (rcDlg.bottom - rcDlg.top) > 20)
  225.     y = rcParent.top  + (((rcParent.bottom - rcParent.top) - (rcDlg.bottom - rcDlg.top)) / 2);
  226.   else
  227.     y = rcParent.top + 60;
  228.  
  229.   SetWindowPos(hDlg,NULL,max(xMin,min(xMax,x)),max(yMin,min(yMax,y)),0,0,SWP_NOZORDER|SWP_NOSIZE);
  230.  
  231. }
  232.  
  233.  
  234. //=============================================================================
  235. //
  236. //  MakeBitmapButton()
  237. //
  238. void MakeBitmapButton(HWND hwnd,int nCtlId,HINSTANCE hInstance,UINT uBmpId)
  239. {
  240.  
  241.   HWND hwndCtl = GetDlgItem(hwnd,nCtlId);
  242.  
  243.   if (PrivateIsAppThemed())
  244.   {
  245.     BITMAP bmp;
  246.     struct { HIMAGELIST himl; RECT margin; UINT uAlign; } bi;
  247.     HBITMAP hBmp = LoadImage(hInstance,MAKEINTRESOURCE(uBmpId),
  248.                              IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS);
  249.     GetObject(hBmp,sizeof(BITMAP),&bmp);
  250.     bi.himl = ImageList_Create(bmp.bmWidth,bmp.bmHeight,ILC_COLORDDB|ILC_MASK,1,0);
  251.     ImageList_AddMasked(bi.himl,hBmp,RGB(128,128,128));
  252.     DeleteObject(hBmp);
  253.     SetRect(&bi.margin,0,0,0,0);
  254.     bi.uAlign = 4/*BUTTON_IMAGELIST_ALIGN_CENTER*/;
  255.     SendMessage(hwndCtl,0x1600+0x0002/*BCM_FIRST+BCM_SETIMAGELIST*/,0,(LPARAM)&bi);
  256.   }
  257.  
  258.   else
  259.   {
  260.     DWORD dwStyle = GetWindowLong(hwndCtl,GWL_STYLE);
  261.     dwStyle |= BS_BITMAP;
  262.     SetWindowLong(hwndCtl,GWL_STYLE,dwStyle);
  263.  
  264.     SendMessage(hwndCtl,BM_SETIMAGE,IMAGE_BITMAP,
  265.       (LPARAM)LoadImage(hInstance,MAKEINTRESOURCE(uBmpId),
  266.       IMAGE_BITMAP,0,0,LR_LOADMAP3DCOLORS));
  267.   }
  268.  
  269. }
  270.  
  271.  
  272. //=============================================================================
  273. //
  274. //  StatusSetText()
  275. //
  276. BOOL StatusSetText(HWND hwnd,UINT nPart,LPCSTR lpszText)
  277. {
  278.  
  279.   UINT uFlags = (nPart == 255) ? nPart|SBT_NOBORDERS : nPart;
  280.   return SendMessage(hwnd,SB_SETTEXT,uFlags,(LPARAM)lpszText);
  281.  
  282. }
  283.  
  284.  
  285. //=============================================================================
  286. //
  287. //  SendWMSize()
  288. //
  289. LRESULT SendWMSize(HWND hwnd)
  290. {
  291.   RECT rc; GetClientRect(hwnd,&rc);
  292.   return(SendMessage(hwnd,WM_SIZE,SIZE_RESTORED,
  293.          MAKELPARAM(rc.right,rc.bottom)));
  294. }
  295.  
  296.  
  297. //=============================================================================
  298. //
  299. //  StatusSetTextID()
  300. //
  301. BOOL StatusSetTextID(HWND hwnd,UINT nPart,UINT uID)
  302. {
  303.  
  304.   char szText[256];
  305.   UINT uFlags = (nPart == 255) ? nPart|SBT_NOBORDERS : nPart;
  306.  
  307.   if (!uID)
  308.   {
  309.     SendMessage(hwnd,SB_SETTEXT,uFlags,0);
  310.     return TRUE;
  311.   }
  312.  
  313.   if (!GetString(uID,szText,256))
  314.     return FALSE;
  315.  
  316.   return SendMessage(hwnd,SB_SETTEXT,uFlags,(LPARAM)szText);
  317.  
  318. }
  319.  
  320.  
  321. //=============================================================================
  322. //
  323. //  StatusCalcPaneWidth()
  324. //
  325. int StatusCalcPaneWidth(HWND hwnd,LPCSTR lpsz)
  326. {
  327.   SIZE  size;
  328.   HDC   hdc   = GetDC(hwnd);
  329.   HFONT hfont = (HFONT)SendMessage(hwnd,WM_GETFONT,0,0);
  330.   HFONT hfold = SelectObject(hdc,hfont);
  331.   int   mmode = SetMapMode(hdc,MM_TEXT);
  332.  
  333.   GetTextExtentPoint32(hdc,lpsz,lstrlen(lpsz),&size);
  334.  
  335.   SetMapMode(hdc,mmode);
  336.   SelectObject(hdc,hfold);
  337.   ReleaseDC(hwnd,hdc);
  338.  
  339.   return(size.cx + 9);
  340. }
  341.  
  342.  
  343. //=============================================================================
  344. //
  345. //  Toolbar_SetButtonImage()
  346. //
  347. void Toolbar_SetButtonImage(HWND hwnd,int idCommand,int iImage)
  348. {
  349.   TBBUTTONINFO tbbi;
  350.  
  351.   tbbi.cbSize = sizeof(TBBUTTONINFO);
  352.   tbbi.dwMask = TBIF_IMAGE;
  353.   tbbi.iImage = iImage;
  354.  
  355.   SendMessage(hwnd,TB_SETBUTTONINFO,(WPARAM)idCommand,(LPARAM)&tbbi);
  356. }
  357.  
  358.  
  359. //=============================================================================
  360. //
  361. //  IsCmdEnabled()
  362. //
  363. BOOL IsCmdEnabled(HWND hwnd,UINT uId)
  364. {
  365.  
  366.   HMENU hmenu;
  367.   UINT ustate;
  368.  
  369.   hmenu = GetMenu(hwnd);
  370.  
  371.   SendMessage(hwnd,WM_INITMENU,(WPARAM)hmenu,0);
  372.  
  373.   ustate = GetMenuState(hmenu,uId,MF_BYCOMMAND);
  374.  
  375.   if (ustate == 0xFFFFFFFF)
  376.     return TRUE;
  377.  
  378.   else
  379.     return (!(ustate & (MF_GRAYED|MF_DISABLED)));
  380.  
  381. }
  382.  
  383.  
  384. //=============================================================================
  385. //
  386. //  FormatString()
  387. //
  388. int FormatString(LPSTR lpOutput,int nOutput,UINT uIdFormat,...)
  389. {
  390.  
  391.   char *p = malloc(nOutput);
  392.  
  393.   if (GetString(uIdFormat,p,nOutput))
  394.     wvsprintf(lpOutput,p,(LPVOID)(&uIdFormat+1));
  395.  
  396.   free(p);
  397.  
  398.   return lstrlen(lpOutput);
  399.  
  400. }
  401.  
  402.  
  403. //=============================================================================
  404. //
  405. //  FormatBytes()
  406. //
  407. void FormatBytes(LPSTR lpOutput,int nOutput,DWORD dwBytes)
  408. {
  409.  
  410.   char tch[256];
  411.   int i;
  412.   double dBytes = dwBytes;
  413.   static const char *pBytes[] = { "Bytes","KB","MB","GB" };
  414.  
  415.   if (dwBytes > 1023)
  416.   {
  417.     for (i = 0; i < 4; i++)
  418.     {
  419.  
  420.       if (dBytes >= 1024.0)
  421.         dBytes /= 1024.0;
  422.  
  423.       else
  424.         break;
  425.     }
  426.     sprintf(tch,"%.2f",dBytes);
  427.     GetNumberFormat(LOCALE_USER_DEFAULT,0,tch,NULL,lpOutput,nOutput);
  428.     lstrcat(lpOutput," ");
  429.     lstrcat(lpOutput,pBytes[i]);
  430.   }
  431.  
  432.   else
  433.   {
  434.     sprintf(lpOutput,"%i",dwBytes);
  435.     FormatNumberStr(lpOutput);
  436.     lstrcat(lpOutput," ");
  437.     lstrcat(lpOutput,pBytes[0]);
  438.   }
  439.  
  440. }
  441.  
  442.  
  443. ///////////////////////////////////////////////////////////////////////////////
  444. //
  445. //
  446. //  Name: PathIsLnkFile()
  447. //
  448. //  Purpose: Determine wheter pszPath is a Windows Shell Link File by
  449. //           comparing the filename extension with ".lnk"
  450. //
  451. //  Manipulates:
  452. //
  453. BOOL PathIsLnkFile(LPCSTR pszPath)
  454. {
  455.  
  456.   //char *pszExt;
  457.  
  458.   char tchResPath[256];
  459.  
  460.   if (!pszPath || !*pszPath)
  461.     return FALSE;
  462.  
  463. /*pszExt = strrchr(pszPath,'.');
  464.  
  465.   if (!pszExt)
  466.     return FALSE;
  467.  
  468.   if (!lstrcmpi(pszExt,".lnk"))
  469.     return TRUE;
  470.  
  471.   else
  472.     return FALSE;*/
  473.  
  474.   //if (!lstrcmpi(PathFindExtension(pszPath),".lnk"))
  475.   //  return TRUE;
  476.  
  477.   //else
  478.   //  return FALSE;
  479.  
  480.   if (lstrcmpi(PathFindExtension(pszPath),".lnk"))
  481.     return FALSE;
  482.  
  483.   else
  484.     return PathGetLnkPath(pszPath,tchResPath,COUNTOF(tchResPath));
  485.  
  486. }
  487.  
  488.  
  489. ///////////////////////////////////////////////////////////////////////////////
  490. //
  491. //
  492. //  Name: PathGetLnkPath()
  493. //
  494. //  Purpose: Try to get the path to which a lnk-file is linked
  495. //
  496. //
  497. //  Manipulates: pszResPath
  498. //
  499. BOOL PathGetLnkPath(LPCSTR pszLnkFile,LPSTR pszResPath,int cchResPath)
  500. {
  501.  
  502.   IShellLink       *psl;
  503.   WIN32_FIND_DATA  fd;
  504.   BOOL             bSucceeded = FALSE;
  505.  
  506.   if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink,NULL,
  507.                                  CLSCTX_INPROC_SERVER,
  508.                                  &IID_IShellLink,&psl)))
  509.   {
  510.     IPersistFile *ppf;
  511.  
  512.     if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,&ppf)))
  513.     {
  514.       WORD wsz[MAX_PATH];
  515.  
  516.       MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,
  517.                           pszLnkFile,-1,wsz,MAX_PATH);
  518.  
  519.       if (SUCCEEDED(ppf->lpVtbl->Load(ppf,wsz,STGM_READ)))
  520.       {
  521.         if (NOERROR == psl->lpVtbl->GetPath(psl,pszResPath,cchResPath,&fd,0))
  522.           bSucceeded = TRUE;
  523.       }
  524.       ppf->lpVtbl->Release(ppf);
  525.     }
  526.     psl->lpVtbl->Release(psl);
  527.   }
  528.  
  529.   // This additional check seems reasonable
  530.   if (!lstrlen(pszResPath))
  531.     bSucceeded = FALSE;
  532.  
  533.   if (bSucceeded) {
  534.     ExpandEnvironmentStringsEx(pszResPath,cchResPath);
  535.     PathCanonicalizeEx(pszResPath); }
  536.  
  537.   return(bSucceeded);
  538.  
  539. }
  540.  
  541.  
  542. ///////////////////////////////////////////////////////////////////////////////
  543. //
  544. //
  545. //  Name: PathIsLnkToDirectory()
  546. //
  547. //  Purpose: Determine wheter pszPath is a Windows Shell Link File which
  548. //           refers to a directory
  549. //
  550. //  Manipulates: pszResPath
  551. //
  552. PathIsLnkToDirectory(LPCSTR pszPath,LPSTR pszResPath,int cchResPath)
  553. {
  554.  
  555.   char tchResPath[MAX_PATH];
  556.  
  557.   if (PathIsLnkFile(pszPath)) {
  558.  
  559.     if (PathGetLnkPath(pszPath,tchResPath,sizeof(char)*COUNTOF(tchResPath))) {
  560.  
  561.       if (PathIsDirectory(tchResPath)) {
  562.  
  563.         lstrcpyn(pszResPath,tchResPath,cchResPath);
  564.         return (TRUE); }
  565.  
  566.       else
  567.         return FALSE; }
  568.  
  569.     else
  570.       return FALSE; }
  571.  
  572.   else
  573.     return FALSE;
  574.  
  575. }
  576.  
  577.  
  578. ///////////////////////////////////////////////////////////////////////////////
  579. //
  580. //
  581. //  Name: PathCreateDeskLnk()
  582. //
  583. //  Purpose: Modified to create a desktop link to Notepad2
  584. //
  585. //  Manipulates:
  586. //
  587. BOOL PathCreateDeskLnk(LPCSTR pszDocument)
  588. {
  589.  
  590.   char tchExeFile[MAX_PATH];
  591.   char tchDocTemp[MAX_PATH];
  592.   char tchArguments[MAX_PATH+16];
  593.   char tchLinkDir[MAX_PATH];
  594.   char tchDescription[64];
  595.  
  596.   char tchLnkFileName[MAX_PATH];
  597.  
  598.   IShellLink *psl;
  599.   BOOL bSucceeded = FALSE;
  600.   BOOL fMustCopy;
  601.  
  602.   if (!pszDocument || lstrlen(pszDocument) == 0)
  603.     return TRUE;
  604.  
  605.   // init strings
  606.   GetModuleFileName(NULL,tchExeFile,COUNTOF(tchExeFile));
  607.  
  608.   lstrcpy(tchDocTemp,pszDocument);
  609.   PathQuoteSpaces(tchDocTemp);
  610.  
  611.   lstrcpy(tchArguments,"-n ");
  612.   lstrcat(tchArguments,tchDocTemp);
  613.  
  614.   GetDefaultOpenWithDir(tchLinkDir,COUNTOF(tchLinkDir));
  615.  
  616.   GetString(IDS_LINKDESCRIPTION,tchDescription,COUNTOF(tchDescription));
  617.  
  618.   // Try to construct a valid filename...
  619.   if (!SHGetNewLinkInfo(pszDocument,tchLinkDir,tchLnkFileName,&fMustCopy,SHGNLI_PREFIXNAME))
  620.     return(FALSE);
  621.  
  622.   if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink,NULL,
  623.                                  CLSCTX_INPROC_SERVER,
  624.                                  &IID_IShellLink,&psl)))
  625.   {
  626.     IPersistFile *ppf;
  627.  
  628.     if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,&ppf)))
  629.     {
  630.       WORD wsz[MAX_PATH];
  631.  
  632.       MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,
  633.                           tchLnkFileName,-1,wsz,MAX_PATH);
  634.  
  635.       psl->lpVtbl->SetPath(psl,tchExeFile);
  636.       psl->lpVtbl->SetArguments(psl,tchArguments);
  637.       psl->lpVtbl->SetDescription(psl,tchDescription);
  638.  
  639.       if (SUCCEEDED(ppf->lpVtbl->Save(ppf,wsz,TRUE)))
  640.         bSucceeded = TRUE;
  641.  
  642.       ppf->lpVtbl->Release(ppf);
  643.     }
  644.     psl->lpVtbl->Release(psl);
  645.   }
  646.  
  647.   return(bSucceeded);
  648.  
  649. }
  650.  
  651.  
  652. ///////////////////////////////////////////////////////////////////////////////
  653. //
  654. //
  655. //  Name: PathCreateFavLnk()
  656. //
  657. //  Purpose: Modified to create a Notepad2 favorites link
  658. //
  659. //  Manipulates:
  660. //
  661. BOOL PathCreateFavLnk(LPCSTR pszName,LPCSTR pszTarget,LPCSTR pszDir)
  662. {
  663.  
  664.   char tchLnkFileName[MAX_PATH];
  665.  
  666.   IShellLink *psl;
  667.   BOOL bSucceeded = FALSE;
  668.  
  669.   if (!pszName || lstrlen(pszName) == 0)
  670.     return TRUE;
  671.  
  672.   lstrcpy(tchLnkFileName,pszDir);
  673.   PathAppend(tchLnkFileName,pszName);
  674.   lstrcat(tchLnkFileName,".lnk");
  675.  
  676.   if (PathFileExists(tchLnkFileName))
  677.     return FALSE;
  678.  
  679.   if (SUCCEEDED(CoCreateInstance(&CLSID_ShellLink,NULL,
  680.                                  CLSCTX_INPROC_SERVER,
  681.                                  &IID_IShellLink,&psl)))
  682.   {
  683.     IPersistFile *ppf;
  684.  
  685.     if (SUCCEEDED(psl->lpVtbl->QueryInterface(psl,&IID_IPersistFile,&ppf)))
  686.     {
  687.       WORD wsz[MAX_PATH];
  688.  
  689.       MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,
  690.                           tchLnkFileName,-1,wsz,MAX_PATH);
  691.  
  692.       psl->lpVtbl->SetPath(psl,pszTarget);
  693.  
  694.       if (SUCCEEDED(ppf->lpVtbl->Save(ppf,wsz,TRUE)))
  695.         bSucceeded = TRUE;
  696.  
  697.       ppf->lpVtbl->Release(ppf);
  698.     }
  699.     psl->lpVtbl->Release(psl);
  700.   }
  701.  
  702.   return(bSucceeded);
  703.  
  704. }
  705.  
  706.  
  707. //=============================================================================
  708. //
  709. //  TrimString()
  710. //
  711. BOOL TrimString(LPSTR lpString)
  712. {
  713.  
  714.   LPSTR psz;
  715.  
  716.  
  717.   if (!lpString || !*lpString)
  718.     return FALSE;
  719.  
  720.   // Trim left
  721.   psz = lpString;
  722.  
  723.   while (*psz == ' ')
  724.     psz = CharNext(psz);
  725.  
  726.   MoveMemory(lpString,psz,lstrlen(psz) + 1);
  727.  
  728.   // Trim right
  729.   psz = StrEnd(lpString);
  730.  
  731.   while (*(psz = CharPrev(lpString,psz)) == ' ')
  732.     *psz = '\0';
  733.  
  734.   return TRUE;
  735.  
  736. }
  737.  
  738.  
  739. //=============================================================================
  740. //
  741. //  ExtractFirstArgument()
  742. //
  743. BOOL ExtractFirstArgument(LPCSTR lpArgs,LPSTR lpArg1,LPSTR lpArg2)
  744. {
  745.  
  746.   LPSTR psz;
  747.   BOOL bQuoted = FALSE;
  748.  
  749.   lstrcpy(lpArg1,lpArgs);
  750.   if (lpArg2)
  751.     *lpArg2 = '\0';
  752.  
  753.   if (!TrimString(lpArg1))
  754.     return FALSE;
  755.  
  756.   if (*lpArg1 == '\"')
  757.   {
  758.     *lpArg1 = ' ';
  759.     TrimString(lpArg1);
  760.     bQuoted = TRUE;
  761.   }
  762.  
  763.   if (bQuoted)
  764.     psz = strchr(lpArg1,'\"');
  765.   else
  766.     psz = strchr(lpArg1,' ');;
  767.  
  768.   if (psz)
  769.   {
  770.     *psz = '\0';
  771.     if (lpArg2)
  772.       lstrcpy(lpArg2,psz + 1);
  773.   }
  774.  
  775.   TrimString(lpArg1);
  776.  
  777.   if (lpArg2)
  778.     TrimString(lpArg2);
  779.  
  780.   return TRUE;
  781.  
  782. }
  783.  
  784.  
  785. //=============================================================================
  786. //
  787. //  PrepareFilterStr()
  788. //
  789. void PrepareFilterStr(LPSTR lpFilter)
  790. {
  791.   LPSTR psz = StrEnd(lpFilter);
  792.   while (psz != lpFilter)
  793.   {
  794.     if (*(psz = CharPrev(lpFilter,psz)) == '\n')
  795.       *psz = '\0';
  796.   }
  797. }
  798.  
  799.  
  800. //=============================================================================
  801. //
  802. //  StrTab2Space() - in place conversion
  803. //
  804. void StrTab2Space(LPSTR lpsz)
  805. {
  806.   char *c;
  807.   while (c = strchr(lpsz,'\t'))
  808.     *c = ' ';
  809. }
  810.  
  811.  
  812. //=============================================================================
  813. //
  814. //  ExpandEnvironmentStringsEx()
  815. //
  816. //  Adjusted for Windows 95
  817. //
  818. void ExpandEnvironmentStringsEx(LPSTR lpSrc,DWORD dwSrc)
  819. {
  820.   char szBuf[312];
  821.  
  822.   if (ExpandEnvironmentStrings(lpSrc,szBuf,COUNTOF(szBuf)))
  823.     lstrcpyn(lpSrc,szBuf,dwSrc);
  824. }
  825.  
  826.  
  827. //=============================================================================
  828. //
  829. //  PathCanonicalizeEx()
  830. //
  831. //
  832. void PathCanonicalizeEx(LPSTR lpSrc)
  833. {
  834.   char szDst[MAX_PATH];
  835.  
  836.   if (PathCanonicalize(szDst,lpSrc))
  837.     lstrcpy(lpSrc,szDst);
  838. }
  839.  
  840.  
  841. //=============================================================================
  842. //
  843. //  GetLongPathNameEx()
  844. //
  845. //  Works fine with Windows 95!
  846. //
  847. extern LPMALLOC g_lpMalloc;
  848.  
  849. DWORD GetLongPathNameEx(LPCSTR lpszShortPath,LPSTR lpszLongPath,DWORD cchBuffer)
  850. {
  851.   WCHAR wszShortPath[MAX_PATH];
  852.   LPSHELLFOLDER lpsfDesktop;
  853.   ULONG chParsed = 0;
  854.   ULONG dwAttributes = 0;
  855.   LPITEMIDLIST  pidl = NULL;
  856.   BOOL fSucceeded = FALSE;
  857.  
  858.   //MessageBox(GetFocus(),lpszShortPath,"GetLongPathNameEx(): lpszShortPath",0);
  859.  
  860.   // Convert lpszShortPath to a UNICODE string
  861.   MultiByteToWideChar(
  862.     CP_ACP,MB_PRECOMPOSED,lpszShortPath,-1,wszShortPath,MAX_PATH);
  863.  
  864.   // Get Desktop Folder
  865.   if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
  866.   {
  867.     // Convert wszShortPath to a pidl
  868.     if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName(
  869.                      lpsfDesktop,NULL,NULL,wszShortPath,&chParsed,&pidl,&dwAttributes))
  870.     {
  871.       if (SHGetPathFromIDList(pidl,lpszLongPath))
  872.         fSucceeded = FALSE;
  873.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
  874.     }
  875.   }
  876.  
  877.   //MessageBox(GetFocus(),lpszLongPath,"GetLongPathNameEx(): lpszLongPath",0);
  878.  
  879.   if (fSucceeded)
  880.     return(lstrlen(lpszLongPath));
  881.   else {
  882.     if (lpszShortPath != lpszLongPath)
  883.       lstrcpy(lpszLongPath,lpszShortPath);
  884.     return(0); }
  885.  
  886.   cchBuffer;
  887. }
  888.  
  889.  
  890. //=============================================================================
  891. //
  892. //  SHGetFileInfo2() - return a default name when the file has been removed
  893. //
  894. DWORD_PTR SHGetFileInfo2(LPCTSTR pszPath,DWORD dwFileAttributes,
  895.                          SHFILEINFO *psfi,UINT cbFileInfo,UINT uFlags)
  896. {
  897.  
  898.   if (PathFileExists(pszPath))
  899.     return SHGetFileInfo(pszPath,dwFileAttributes,psfi,cbFileInfo,uFlags);
  900.  
  901.   else
  902.     return SHGetFileInfo(pszPath,FILE_ATTRIBUTE_NORMAL,
  903.                          psfi,cbFileInfo,uFlags|SHGFI_USEFILEATTRIBUTES);
  904.  
  905. }
  906.  
  907.  
  908. //=============================================================================
  909. //
  910. //  FormatNumberStr()
  911. //
  912. int FormatNumberStr(LPSTR lpNumberStr)
  913. {
  914.   char *c;
  915.   char szSep[8];
  916.   int  i = 0;
  917.  
  918.   if (!lstrlen(lpNumberStr))
  919.     return(0);
  920.  
  921.   if (!GetLocaleInfo(LOCALE_USER_DEFAULT,
  922.                      LOCALE_STHOUSAND,
  923.                      szSep,
  924.                      COUNTOF(szSep)))
  925.     szSep[0] = '\'';
  926.  
  927.   c = StrEnd(lpNumberStr);
  928.  
  929.   while ((c = CharPrev(lpNumberStr,c)) != lpNumberStr)
  930.   {
  931.     if (++i == 3)
  932.     {
  933.       i = 0;
  934.       MoveMemory(c+1,c,lstrlen(c)+1);
  935.       *c = szSep[0];
  936.     }
  937.   }
  938.  
  939.   return(lstrlen(lpNumberStr));
  940. }
  941.  
  942.  
  943. //=============================================================================
  944. //
  945. //  SetDlgItemIntEx()
  946. //
  947. BOOL SetDlgItemIntEx(HWND hwnd,int nIdItem,UINT uValue)
  948. {
  949.   char szBuf[64];
  950.  
  951.   wsprintf(szBuf,"%u",uValue);
  952.   FormatNumberStr(szBuf);
  953.  
  954.   return(SetDlgItemText(hwnd,nIdItem,szBuf));
  955. }
  956.  
  957.  
  958. //=============================================================================
  959. //
  960. //  A2W: Convert Dialog Item Text form Unicode to UTF-8 and vice versa
  961. //
  962. UINT GetDlgItemTextA2W(UINT uCP,HWND hDlg,int nIDDlgItem,LPSTR lpString,int nMaxCount)
  963. {
  964.   WCHAR wsz[256];
  965.   UINT uRet = GetDlgItemTextW(hDlg,nIDDlgItem,wsz,256);
  966.   WCharToMBCS(uCP,wsz,lpString,nMaxCount);
  967.   return uRet;
  968. }
  969.  
  970. UINT SetDlgItemTextA2W(UINT uCP,HWND hDlg,int nIDDlgItem,LPSTR lpString)
  971. {
  972.   WCHAR wsz[256];
  973.   MBCSToWChar(uCP,lpString,wsz,256 / sizeof(WCHAR));
  974.   return SetDlgItemTextW(hDlg,nIDDlgItem,wsz);
  975. }
  976.  
  977. LRESULT ComboBox_AddStringA2W(UINT uCP,HWND hwnd,LPCSTR lpString)
  978. {
  979.   WCHAR wsz[256];
  980.   MBCSToWChar(uCP,lpString,wsz,256 / sizeof(WCHAR));
  981.   return SendMessageW(hwnd,CB_ADDSTRING,0,(LPARAM)wsz);
  982. }
  983.  
  984.  
  985. //=============================================================================
  986. //
  987. //  CodePageFromCharSet()
  988. //
  989. UINT CodePageFromCharSet(UINT uCharSet)
  990. {
  991.   CHARSETINFO ci;
  992.   if (TranslateCharsetInfo((DWORD*)uCharSet,&ci,TCI_SRCCHARSET))
  993.     return(ci.ciACP);
  994.   else
  995.     return(GetACP());
  996. }
  997.  
  998.  
  999. //=============================================================================
  1000. //
  1001. //  GetDefaultFavoritesDir()
  1002. //
  1003. void GetDefaultFavoritesDir(LPSTR lpFavDir,int cchFavDir)
  1004. {
  1005.  
  1006.   LPITEMIDLIST pidl;
  1007.   LPMALLOC     lpMalloc;
  1008.  
  1009.   if (NOERROR == SHGetSpecialFolderLocation(
  1010.                    NULL,CSIDL_PERSONAL,&pidl))
  1011.   {
  1012.     SHGetPathFromIDList(pidl,lpFavDir);
  1013.  
  1014.     if (NOERROR == SHGetMalloc(&lpMalloc))
  1015.     {
  1016.       lpMalloc->lpVtbl->Free(lpMalloc,pidl);
  1017.       lpMalloc->lpVtbl->Release(lpMalloc);
  1018.     }
  1019.  
  1020.   }
  1021.  
  1022.   else
  1023.     GetWindowsDirectory(lpFavDir,cchFavDir);
  1024.  
  1025. }
  1026.  
  1027.  
  1028. //=============================================================================
  1029. //
  1030. //  GetDefaultOpenWithDir()
  1031. //
  1032. void GetDefaultOpenWithDir(LPSTR lpOpenWithDir,int cchOpenWithDir)
  1033. {
  1034.  
  1035.   LPITEMIDLIST pidl;
  1036.   LPMALLOC     lpMalloc;
  1037.  
  1038.   if (NOERROR == SHGetSpecialFolderLocation(
  1039.                    NULL,CSIDL_DESKTOP,&pidl))
  1040.   {
  1041.     SHGetPathFromIDList(pidl,lpOpenWithDir);
  1042.  
  1043.     if (NOERROR == SHGetMalloc(&lpMalloc))
  1044.     {
  1045.       lpMalloc->lpVtbl->Free(lpMalloc,pidl);
  1046.       lpMalloc->lpVtbl->Release(lpMalloc);
  1047.     }
  1048.  
  1049.   }
  1050.  
  1051.   else
  1052.     GetWindowsDirectory(lpOpenWithDir,cchOpenWithDir);
  1053.  
  1054. }
  1055.  
  1056.  
  1057. //=============================================================================
  1058. //
  1059. //  LoadXPM() - Load XPM Resource, must be freed by LocalFree()
  1060. //
  1061. LPSTR LoadXPM(HINSTANCE hInstRes,UINT uidRes)
  1062. {
  1063.   HRSRC hResInfo;
  1064.   HGLOBAL hResData;
  1065.   LPVOID lpvResData;
  1066.   DWORD dwResSize;
  1067.  
  1068.   LPSTR lpszXPM = NULL;
  1069.  
  1070.   if (!(hResInfo = FindResource(hInstRes,MAKEINTRESOURCE(uidRes),"xpm")))
  1071.     return NULL;
  1072.  
  1073.   if (hResData = LoadResource(hInstRes,hResInfo))
  1074.   {
  1075.     dwResSize = SizeofResource(hInstRes,hResInfo);
  1076.     if (lpvResData = LockResource(hResData))
  1077.     {
  1078.       lpszXPM = LocalAlloc(LPTR,dwResSize + 16);
  1079.       CopyMemory(lpszXPM ,lpvResData,dwResSize);
  1080.     }
  1081.   }
  1082.   return lpszXPM;
  1083. }
  1084.  
  1085.  
  1086. /*
  1087.  
  1088.   MinimizeToTray - Copyright 2000 Matthew Ellis <m.t.ellis@bigfoot.com>
  1089.  
  1090.   Changes made by flo:
  1091.    - Commented out: #include "stdafx.h"
  1092.    - Moved variable declaration: APPBARDATA appBarData;
  1093.  
  1094. */
  1095.  
  1096. // MinimizeToTray
  1097. //
  1098. // A couple of routines to show how to make it produce a custom caption
  1099. // animation to make it look like we are minimizing to and maximizing
  1100. // from the system tray
  1101. //
  1102. // These routines are public domain, but it would be nice if you dropped
  1103. // me a line if you use them!
  1104. //
  1105. // 1.0 29.06.2000 Initial version
  1106. // 1.1 01.07.2000 The window retains it's place in the Z-order of windows
  1107. //     when minimized/hidden. This means that when restored/shown, it doen't
  1108. //     always appear as the foreground window unless we call SetForegroundWindow
  1109. //
  1110. // Copyright 2000 Matthew Ellis <m.t.ellis@bigfoot.com>
  1111. /*#include "stdafx.h"*/
  1112.  
  1113. // Odd. VC++6 winuser.h has IDANI_CAPTION defined (as well as IDANI_OPEN and
  1114. // IDANI_CLOSE), but the Platform SDK only has IDANI_OPEN...
  1115.  
  1116. // I don't know what IDANI_OPEN or IDANI_CLOSE do. Trying them in this code
  1117. // produces nothing. Perhaps they were intended for window opening and closing
  1118. // like the MAC provides...
  1119. #ifndef IDANI_OPEN
  1120. #define IDANI_OPEN 1
  1121. #endif
  1122. #ifndef IDANI_CLOSE
  1123. #define IDANI_CLOSE 2
  1124. #endif
  1125. #ifndef IDANI_CAPTION
  1126. #define IDANI_CAPTION 3
  1127. #endif
  1128.  
  1129. #define DEFAULT_RECT_WIDTH 150
  1130. #define DEFAULT_RECT_HEIGHT 30
  1131.  
  1132. // Returns the rect of where we think the system tray is. This will work for
  1133. // all current versions of the shell. If explorer isn't running, we try our
  1134. // best to work with a 3rd party shell. If we still can't find anything, we
  1135. // return a rect in the lower right hand corner of the screen
  1136. static VOID GetTrayWndRect(LPRECT lpTrayRect)
  1137. {
  1138.   APPBARDATA appBarData;
  1139.   // First, we'll use a quick hack method. We know that the taskbar is a window
  1140.   // of class Shell_TrayWnd, and the status tray is a child of this of class
  1141.   // TrayNotifyWnd. This provides us a window rect to minimize to. Note, however,
  1142.   // that this is not guaranteed to work on future versions of the shell. If we
  1143.   // use this method, make sure we have a backup!
  1144.   HWND hShellTrayWnd=FindWindowEx(NULL,NULL,TEXT("Shell_TrayWnd"),NULL);
  1145.   if(hShellTrayWnd)
  1146.   {
  1147.     HWND hTrayNotifyWnd=FindWindowEx(hShellTrayWnd,NULL,TEXT("TrayNotifyWnd"),NULL);
  1148.     if(hTrayNotifyWnd)
  1149.     {
  1150.       GetWindowRect(hTrayNotifyWnd,lpTrayRect);
  1151.       return;
  1152.     }
  1153.   }
  1154.  
  1155.   // OK, we failed to get the rect from the quick hack. Either explorer isn't
  1156.   // running or it's a new version of the shell with the window class names
  1157.   // changed (how dare Microsoft change these undocumented class names!) So, we
  1158.   // try to find out what side of the screen the taskbar is connected to. We
  1159.   // know that the system tray is either on the right or the bottom of the
  1160.   // taskbar, so we can make a good guess at where to minimize to
  1161.   /*APPBARDATA appBarData;*/
  1162.   appBarData.cbSize=sizeof(appBarData);
  1163.   if(SHAppBarMessage(ABM_GETTASKBARPOS,&appBarData))
  1164.   {
  1165.     // We know the edge the taskbar is connected to, so guess the rect of the
  1166.     // system tray. Use various fudge factor to make it look good
  1167.     switch(appBarData.uEdge)
  1168.     {
  1169.       case ABE_LEFT:
  1170.       case ABE_RIGHT:
  1171.   // We want to minimize to the bottom of the taskbar
  1172.   lpTrayRect->top=appBarData.rc.bottom-100;
  1173.   lpTrayRect->bottom=appBarData.rc.bottom-16;
  1174.   lpTrayRect->left=appBarData.rc.left;
  1175.   lpTrayRect->right=appBarData.rc.right;
  1176.   break;
  1177.  
  1178.       case ABE_TOP:
  1179.       case ABE_BOTTOM:
  1180.   // We want to minimize to the right of the taskbar
  1181.   lpTrayRect->top=appBarData.rc.top;
  1182.   lpTrayRect->bottom=appBarData.rc.bottom;
  1183.   lpTrayRect->left=appBarData.rc.right-100;
  1184.   lpTrayRect->right=appBarData.rc.right-16;
  1185.   break;
  1186.     }
  1187.  
  1188.     return;
  1189.   }
  1190.  
  1191.   // Blimey, we really aren't in luck. It's possible that a third party shell
  1192.   // is running instead of explorer. This shell might provide support for the
  1193.   // system tray, by providing a Shell_TrayWnd window (which receives the
  1194.   // messages for the icons) So, look for a Shell_TrayWnd window and work out
  1195.   // the rect from that. Remember that explorer's taskbar is the Shell_TrayWnd,
  1196.   // and stretches either the width or the height of the screen. We can't rely
  1197.   // on the 3rd party shell's Shell_TrayWnd doing the same, in fact, we can't
  1198.   // rely on it being any size. The best we can do is just blindly use the
  1199.   // window rect, perhaps limiting the width and height to, say 150 square.
  1200.   // Note that if the 3rd party shell supports the same configuraion as
  1201.   // explorer (the icons hosted in NotifyTrayWnd, which is a child window of
  1202.   // Shell_TrayWnd), we would already have caught it above
  1203.   hShellTrayWnd=FindWindowEx(NULL,NULL,TEXT("Shell_TrayWnd"),NULL);
  1204.   if(hShellTrayWnd)
  1205.   {
  1206.     GetWindowRect(hShellTrayWnd,lpTrayRect);
  1207.     if(lpTrayRect->right-lpTrayRect->left>DEFAULT_RECT_WIDTH)
  1208.       lpTrayRect->left=lpTrayRect->right-DEFAULT_RECT_WIDTH;
  1209.     if(lpTrayRect->bottom-lpTrayRect->top>DEFAULT_RECT_HEIGHT)
  1210.       lpTrayRect->top=lpTrayRect->bottom-DEFAULT_RECT_HEIGHT;
  1211.  
  1212.     return;
  1213.   }
  1214.  
  1215.   // OK. Haven't found a thing. Provide a default rect based on the current work
  1216.   // area
  1217.   SystemParametersInfo(SPI_GETWORKAREA,0,lpTrayRect,0);
  1218.   lpTrayRect->left=lpTrayRect->right-DEFAULT_RECT_WIDTH;
  1219.   lpTrayRect->top=lpTrayRect->bottom-DEFAULT_RECT_HEIGHT;
  1220. }
  1221.  
  1222. // Check to see if the animation has been disabled
  1223. static BOOL GetDoAnimateMinimize(VOID)
  1224. {
  1225.   ANIMATIONINFO ai;
  1226.  
  1227.   ai.cbSize=sizeof(ai);
  1228.   SystemParametersInfo(SPI_GETANIMATION,sizeof(ai),&ai,0);
  1229.  
  1230.   return ai.iMinAnimate?TRUE:FALSE;
  1231. }
  1232.  
  1233. VOID MinimizeWndToTray(HWND hWnd)
  1234. {
  1235.   if(GetDoAnimateMinimize())
  1236.   {
  1237.     RECT rcFrom,rcTo;
  1238.  
  1239.     // Get the rect of the window. It is safe to use the rect of the whole
  1240.     // window - DrawAnimatedRects will only draw the caption
  1241.     GetWindowRect(hWnd,&rcFrom);
  1242.     GetTrayWndRect(&rcTo);
  1243.  
  1244.     // Get the system to draw our animation for us
  1245.     DrawAnimatedRects(hWnd,IDANI_CAPTION,&rcFrom,&rcTo);
  1246.   }
  1247.  
  1248.   // Add the tray icon. If we add it before the call to DrawAnimatedRects,
  1249.   // the taskbar gets erased, but doesn't get redrawn until DAR finishes.
  1250.   // This looks untidy, so call the functions in this order
  1251.  
  1252.   // Hide the window
  1253.   ShowWindow(hWnd,SW_HIDE);
  1254. }
  1255.  
  1256. VOID RestoreWndFromTray(HWND hWnd)
  1257. {
  1258.   if(GetDoAnimateMinimize())
  1259.   {
  1260.     // Get the rect of the tray and the window. Note that the window rect
  1261.     // is still valid even though the window is hidden
  1262.     RECT rcFrom,rcTo;
  1263.     GetTrayWndRect(&rcFrom);
  1264.     GetWindowRect(hWnd,&rcTo);
  1265.  
  1266.     // Get the system to draw our animation for us
  1267.     DrawAnimatedRects(hWnd,IDANI_CAPTION,&rcFrom,&rcTo);
  1268.   }
  1269.  
  1270.   // Show the window, and make sure we're the foreground window
  1271.   ShowWindow(hWnd,SW_SHOW);
  1272.   SetActiveWindow(hWnd);
  1273.   SetForegroundWindow(hWnd);
  1274.  
  1275.   // Remove the tray icon. As described above, remove the icon after the
  1276.   // call to DrawAnimatedRects, or the taskbar will not refresh itself
  1277.   // properly until DAR finished
  1278. }
  1279.  
  1280.  
  1281.  
  1282. ///   End of Helpers.c   \\\
  1283.