home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 March / CMCD0304.ISO / Software / Freeware / Programare / nullsoft / nsis20.exe / Contrib / StartMenu / StartMenu.c < prev    next >
C/C++ Source or Header  |  2004-01-04  |  10KB  |  406 lines

  1. #include <windows.h>
  2. #include <shlobj.h>
  3. #include "../exdll/exdll.h"
  4. #include "resource.h"
  5.  
  6. HINSTANCE g_hInstance;
  7.  
  8. HWND hwParent;
  9. HWND hwChild;
  10. HWND g_hwStartMenuSelect;
  11. HWND g_hwDirList;
  12.  
  13. char buf[1024];
  14. char text[1024];
  15. char progname[1024];
  16. char lastused[1024];
  17. char checkbox[1024];
  18.  
  19. int autoadd = 0;
  20. int g_done = 0;
  21. int noicon = 0;
  22. int rtl = 0;
  23.  
  24. void *lpWndProcOld;
  25.  
  26. BOOL CALLBACK dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  27. BOOL CALLBACK ParentWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  28. void AddFolderFromReg(int nFolder);
  29.  
  30. void __declspec(dllexport) Select(HWND hwndParent, int string_size, char *variables, stack_t **stacktop)
  31. {
  32.   HWND hwStartMenuSelect;
  33.  
  34.   hwParent = hwndParent;
  35.  
  36.   EXDLL_INIT();
  37.  
  38.   {
  39.     hwChild = GetDlgItem(hwndParent, 1018);
  40.     if (!hwChild)
  41.     {
  42.       pushstring("error finding childwnd");
  43.       return;
  44.     }
  45.  
  46.     popstring(buf);
  47.  
  48.     while (buf[0] == '/')
  49.     {
  50.       if (!lstrcmpi(buf+1, "noicon"))
  51.       {
  52.         noicon = 1;
  53.       }
  54.       else if (!lstrcmpi(buf+1, "rtl"))
  55.       {
  56.         rtl = 1;
  57.       }
  58.       else if (!lstrcmpi(buf+1, "text"))
  59.       {
  60.         popstring(text);
  61.       }
  62.       else if (!lstrcmpi(buf+1, "autoadd"))
  63.       {
  64.         autoadd = 1;
  65.       }
  66.       else if (!lstrcmpi(buf+1, "lastused"))
  67.       {
  68.         popstring(lastused);
  69.       }
  70.       else if (!lstrcmpi(buf+1, "checknoshortcuts"))
  71.       {
  72.         popstring(checkbox);
  73.       }
  74.       if (popstring(buf))
  75.         *buf = 0;
  76.     }
  77.     if (*buf)
  78.       lstrcpy(progname, buf);
  79.     else
  80.     {
  81.       pushstring("error reading parameters");
  82.       return;
  83.     }
  84.  
  85.     hwStartMenuSelect = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG), hwndParent, dlgProc);
  86.     g_hwStartMenuSelect = hwStartMenuSelect;
  87.     if (!hwStartMenuSelect)
  88.     {
  89.       pushstring("error creating dialog");
  90.       g_done = 1;
  91.     }
  92.     else
  93.     {
  94.       lpWndProcOld = (void *) SetWindowLong(hwndParent, DWL_DLGPROC, (long) ParentWndProc);
  95.     }
  96.  
  97.     while (!g_done)
  98.     {
  99.       MSG msg;
  100.       int nResult = GetMessage(&msg, NULL, 0, 0);
  101.       if (!IsDialogMessage(hwStartMenuSelect,&msg) && !IsDialogMessage(hwndParent,&msg) && !TranslateMessage(&msg))
  102.         DispatchMessage(&msg);
  103.     }
  104.     DestroyWindow(hwStartMenuSelect);
  105.  
  106.     SetWindowLong(hwndParent, DWL_DLGPROC, (long) lpWndProcOld);
  107.   }
  108. }
  109.  
  110. static BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  111. {
  112.   BOOL bRes = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam);
  113.   if (message == WM_NOTIFY_OUTER_NEXT && !bRes)
  114.   {
  115.     // if leave function didn't abort (lRes != 0 in that case)
  116.     PostMessage(g_hwStartMenuSelect,WM_USER+666,wParam,0);
  117.   }
  118.   return bRes;
  119. }
  120.  
  121. void AddRTLStyle(HWND hWnd, long dwStyle)
  122. {
  123.   long s;
  124.  
  125.   s = GetWindowLong(hWnd, GWL_STYLE);
  126.   SetWindowLong(hWnd, GWL_STYLE, s | dwStyle);
  127.   s = GetWindowLong(hWnd, GWL_EXSTYLE);
  128.   SetWindowLong(hWnd, GWL_EXSTYLE, s | WS_EX_RIGHT | WS_EX_RTLREADING);
  129. }
  130.  
  131. #define ProgressiveSetWindowPos(hwWindow, x, cx, cy) \
  132.   MoveWindow( \
  133.     hwWindow, \
  134.     x, \
  135.     y_offset, \
  136.     cx, \
  137.     cy, \
  138.     FALSE \
  139.   ); \
  140.    \
  141.   y_offset += cy + 3;
  142.  
  143. BOOL CALLBACK dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  144. {
  145.   HWND hwLocation = GetDlgItem(hwndDlg, IDC_LOCATION);
  146.   HWND hwDirList = GetDlgItem(hwndDlg, IDC_DIRLIST);
  147.   HWND hwCheckBox = GetDlgItem(hwndDlg, IDC_CHECK);
  148.  
  149.   switch (uMsg)
  150.   {
  151.     case WM_INITDIALOG:
  152.     {
  153.       HWND hwIcon;
  154.       HWND hwText;
  155.  
  156.       RECT dialog_r, temp_r;
  157.  
  158.       HFONT hFont = (HFONT) SendMessage(hwParent, WM_GETFONT, 0, 0);
  159.  
  160.       int y_offset = 0;
  161.  
  162.       int width, height;
  163.  
  164.       int baseUnitY;
  165.  
  166.       // Init dialog unit conversion
  167.  
  168.       {
  169.         TEXTMETRIC tm;
  170.         HDC hDC;
  171.  
  172.         hDC = GetDC(hwndDlg);
  173.         SelectObject(hDC, hFont);
  174.  
  175.         GetTextMetrics(hDC, &tm);
  176.         baseUnitY = tm.tmHeight;
  177.  
  178.         ReleaseDC(hwndDlg, hDC);
  179.       }
  180.  
  181.       GetWindowRect(hwChild, &dialog_r);
  182.       ScreenToClient(hwParent, (LPPOINT) &dialog_r);
  183.       ScreenToClient(hwParent, ((LPPOINT) &dialog_r) + 1);
  184.  
  185.       width = dialog_r.right - dialog_r.left;
  186.       height = dialog_r.bottom - dialog_r.top;
  187.  
  188.       MoveWindow(
  189.         hwndDlg,
  190.         dialog_r.left,
  191.         dialog_r.top,
  192.         width,
  193.         height,
  194.         FALSE
  195.       );
  196.  
  197.       hwIcon = GetDlgItem(hwndDlg, IDC_NSISICON);
  198.       hwText = GetDlgItem(hwndDlg, IDC_TEXT);
  199.       g_hwDirList = hwDirList;
  200.  
  201.       SendMessage(hwndDlg, WM_SETFONT, (WPARAM) hFont, TRUE);
  202.       SendMessage(hwIcon, WM_SETFONT, (WPARAM) hFont, TRUE);
  203.       SendMessage(hwText, WM_SETFONT, (WPARAM) hFont, TRUE);
  204.       SendMessage(hwLocation, WM_SETFONT, (WPARAM) hFont, TRUE);
  205.       SendMessage(hwDirList, WM_SETFONT, (WPARAM) hFont, TRUE);
  206.       SendMessage(hwCheckBox, WM_SETFONT, (WPARAM) hFont, TRUE);
  207.  
  208.       if (rtl)
  209.       {
  210.         AddRTLStyle(hwText, SS_RIGHT);
  211.         AddRTLStyle(hwLocation, ES_RIGHT);
  212.         AddRTLStyle(hwDirList, 0);
  213.         AddRTLStyle(hwCheckBox, BS_RIGHT | BS_LEFTTEXT);
  214.       }
  215.  
  216.       GetClientRect(hwIcon, &temp_r);
  217.  
  218.       if (!noicon)
  219.       {
  220.         SendMessage(
  221.           hwIcon,
  222.           STM_SETIMAGE,
  223.           IMAGE_ICON,
  224.           (LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(103))
  225.         );
  226.  
  227.         MoveWindow(
  228.           hwIcon,
  229.           rtl ? width - temp_r.right : 0,
  230.           0,
  231.           temp_r.right,
  232.           temp_r.bottom,
  233.           FALSE
  234.         );
  235.  
  236.         temp_r.right += 3;
  237.       }
  238.       else
  239.       {
  240.         ShowWindow(hwIcon, SW_HIDE);
  241.         
  242.         temp_r.right = 0;
  243.       }
  244.  
  245.       if (rtl)
  246.       {
  247.         ProgressiveSetWindowPos(
  248.           hwText,
  249.           0,
  250.           width - temp_r.right,
  251.           3 * baseUnitY //MulDiv(24, baseUnitY, 8);
  252.         );
  253.       }
  254.       else
  255.       {
  256.         ProgressiveSetWindowPos(
  257.           hwText,
  258.           temp_r.right,
  259.           width - temp_r.right + 3,
  260.           3 * baseUnitY //MulDiv(24, baseUnitY, 8);
  261.         );
  262.       }
  263.  
  264.       SetWindowText(hwText, *text ? text : "Select the Start Menu folder in which you would like to create the program's shortcuts:");
  265.  
  266.       ProgressiveSetWindowPos(
  267.         hwLocation,
  268.         0,
  269.         width,
  270.         MulDiv(12, baseUnitY, 8)
  271.       );
  272.  
  273.       if (*lastused == '>')
  274.       {
  275.         CheckDlgButton(hwndDlg, IDC_CHECK, BST_CHECKED);
  276.         lstrcpy(lastused, lstrcpy(buf, lastused) + 1);
  277.         EnableWindow(hwDirList, FALSE);
  278.         EnableWindow(hwLocation, FALSE);
  279.       }
  280.  
  281.       SetWindowText(hwLocation, *lastused ? lastused : progname);
  282.  
  283.       temp_r.bottom = MulDiv(8, baseUnitY, 8);
  284.  
  285.       ProgressiveSetWindowPos(
  286.         hwDirList,
  287.         0,
  288.         width,
  289.         height - y_offset - (*checkbox ? temp_r.bottom + 3 : 0)
  290.       );
  291.  
  292.       if (*checkbox)
  293.       {
  294.         ProgressiveSetWindowPos(
  295.           hwCheckBox,
  296.           0,
  297.           width,
  298.           temp_r.bottom
  299.         );
  300.  
  301.         ShowWindow(hwCheckBox, SW_SHOWNA);
  302.         SetWindowText(hwCheckBox, checkbox);
  303.       }
  304.  
  305.       AddFolderFromReg(CSIDL_COMMON_PROGRAMS);
  306.       AddFolderFromReg(CSIDL_PROGRAMS);
  307.  
  308.       // Tell NSIS to remove old inner dialog and pass handle of the new inner dialog
  309.       SendMessage(hwParent, WM_NOTIFY_CUSTOM_READY, (WPARAM)hwndDlg, 0);
  310.       ShowWindow(hwndDlg, SW_SHOWNA);
  311.       if (IsDlgButtonChecked(hwndDlg, IDC_CHECK) == BST_CHECKED)
  312.         SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwCheckBox, TRUE);
  313.       else
  314.         SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwLocation, TRUE);
  315.     }
  316.     break;
  317.     case WM_COMMAND:
  318.       if (LOWORD(wParam) == IDC_DIRLIST && HIWORD(wParam) == LBN_SELCHANGE)
  319.       {
  320.         SendMessage(hwDirList, LB_GETTEXT, SendMessage(hwDirList, LB_GETCURSEL, 0, 0), (WPARAM)buf);
  321.         if (autoadd)
  322.           lstrcat(lstrcat(buf, "\\"), progname);
  323.         SetWindowText(hwLocation, buf);
  324.       }
  325.       else if (LOWORD(wParam) == IDC_CHECK && HIWORD(wParam) == BN_CLICKED)
  326.       {
  327.         BOOL bEnable = IsDlgButtonChecked(hwndDlg, IDC_CHECK) != BST_CHECKED;
  328.         EnableWindow(hwDirList, bEnable);
  329.         EnableWindow(hwLocation, bEnable);
  330.       }
  331.     break;
  332.     case WM_USER+666:
  333.       g_done = 1;
  334.       if (wParam == NOTIFY_BYE_BYE)
  335.         pushstring("cancel");
  336.       else
  337.       {
  338.         if (IsDlgButtonChecked(hwndDlg, IDC_CHECK) == BST_CHECKED)
  339.         {
  340.           short *sbuf = (short *) buf;
  341.           *sbuf = *(short *) ">";
  342.         }
  343.         else *buf = 0;
  344.         GetWindowText(hwLocation, buf + (*buf ? 1 : 0), MAX_PATH);
  345.         pushstring(buf);
  346.         pushstring("success");
  347.       }
  348.     break;
  349.   }
  350.     return 0;
  351. }
  352.  
  353. BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
  354. {
  355.   g_hInstance=hInst;
  356.     return TRUE;
  357. }
  358.  
  359. void AddFolderFromReg(int nFolder)
  360. {
  361.   //DWORD idx;
  362.   WIN32_FIND_DATA FileData;
  363.   HANDLE hSearch;
  364.  
  365.   LPMALLOC ppMalloc;
  366.   if (SHGetMalloc(&ppMalloc) == NOERROR)
  367.   {
  368.     LPITEMIDLIST ppidl;
  369.  
  370.     buf[0] = 0;
  371.     if (SHGetSpecialFolderLocation(hwParent, nFolder, &ppidl) == S_OK)
  372.     {
  373.       SHGetPathFromIDList(ppidl, buf);
  374.       ppMalloc->lpVtbl->Free(ppMalloc, ppidl);
  375.     }
  376.  
  377.     ppMalloc->lpVtbl->Release(ppMalloc);
  378.   }
  379.  
  380.   if (!buf[0])
  381.     return;
  382.  
  383.   lstrcat(buf, "\\*.*");
  384.   hSearch = FindFirstFile(buf, &FileData);
  385.   if (hSearch != INVALID_HANDLE_VALUE) 
  386.   {
  387.     do
  388.     {
  389.       if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  390.       {
  391.         if (*(WORD*)FileData.cFileName != *(WORD*)".")
  392.         {
  393.           if (*(WORD*)FileData.cFileName != *(WORD*)".." || FileData.cFileName[2])
  394.           {
  395.             if (SendMessage(g_hwDirList, LB_FINDSTRINGEXACT, -1, (LPARAM)FileData.cFileName) == LB_ERR)
  396.               SendMessage(g_hwDirList, LB_ADDSTRING, 0, (LPARAM)FileData.cFileName);
  397.             /*idx = */
  398.             /*SendMessage(hwDirList, LB_SETITEMDATA, (WPARAM)idx,
  399.               (LPARAM)ExtractAssociatedIcon(g_hInstance, FileData.cFileName, (WORD*)&idx));*/
  400.           }
  401.         }
  402.       }
  403.     } while (FindNextFile(hSearch, &FileData));
  404.     FindClose(hSearch);
  405.   }
  406. }