NSIS/Contrib/StartMenu/StartMenu.c
wizou 752d7d239a Jim Park's Unicode NSIS merging - Step 1 : switch to TCHARs where relevant.
Compiler output is identical before & after this step

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/branches/wizou@6036 212acab6-be3b-0410-9dea-997c60f758d6
2010-03-24 17:22:56 +00:00

466 lines
11 KiB
C

#include <windows.h>
#include <shlobj.h>
#include <nsis/pluginapi.h> // nsis plugin
#include "resource.h"
HINSTANCE g_hInstance;
HWND hwParent;
HWND hwChild;
HWND g_hwStartMenuSelect;
HWND g_hwDirList;
TCHAR buf[1024];
TCHAR text[1024];
TCHAR progname[1024];
TCHAR lastused[1024];
TCHAR checkbox[1024];
int autoadd;
int g_done;
int noicon;
int rtl;
void *lpWndProcOld;
void (__stdcall *validate_filename)(TCHAR *);
BOOL CALLBACK dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
static BOOL CALLBACK ParentWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void AddFolderFromReg(int nFolder);
static UINT_PTR PluginCallback(enum NSPIM msg)
{
return 0;
}
void __declspec(dllexport) Init(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters *extra)
{
HWND hwStartMenuSelect;
hwParent = hwndParent;
validate_filename = extra->validate_filename;
EXDLL_INIT();
extra->RegisterPluginCallback(g_hInstance, PluginCallback);
g_done = 0;
noicon = 0;
rtl = 0;
autoadd = 0;
text[0] = 0;
progname[0] = 0;
lastused[0] = 0;
checkbox[0] = 0;
g_hwStartMenuSelect = NULL;
{
hwChild = GetDlgItem(hwndParent, 1018);
if (!hwChild)
{
pushstring(_T("error finding childwnd"));
return;
}
popstring(buf);
while (buf[0] == _T('/'))
{
if (!lstrcmpi(buf+1, _T("noicon")))
{
noicon = 1;
}
else if (!lstrcmpi(buf+1, _T("rtl")))
{
rtl = 1;
}
else if (!lstrcmpi(buf+1, _T("text")))
{
popstring(text);
}
else if (!lstrcmpi(buf+1, _T("autoadd")))
{
autoadd = 1;
}
else if (!lstrcmpi(buf+1, _T("lastused")))
{
popstring(lastused);
}
else if (!lstrcmpi(buf+1, _T("checknoshortcuts")))
{
popstring(checkbox);
}
if (popstring(buf))
{
*buf = 0;
}
}
if (*buf)
{
lstrcpy(progname, buf);
}
else
{
pushstring(_T("error reading parameters"));
return;
}
hwStartMenuSelect = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG), hwndParent, dlgProc);
g_hwStartMenuSelect = hwStartMenuSelect;
if (!hwStartMenuSelect)
{
pushstring(_T("error creating dialog"));
return;
}
else
{
lpWndProcOld = (void *) SetWindowLong(hwndParent, DWL_DLGPROC, (long) ParentWndProc);
wsprintf(buf, _T("%u"), hwStartMenuSelect);
pushstring(buf);
}
}
}
void __declspec(dllexport) Show(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop)
{
HWND hwStartMenuSelect = g_hwStartMenuSelect;
if (!hwStartMenuSelect)
{
return;
}
while (!g_done)
{
MSG msg;
GetMessage(&msg, NULL, 0, 0);
if (!IsDialogMessage(hwStartMenuSelect,&msg) && !IsDialogMessage(hwndParent,&msg) && !TranslateMessage(&msg))
DispatchMessage(&msg);
}
DestroyWindow(hwStartMenuSelect);
SetWindowLong(hwndParent, DWL_DLGPROC, (long) lpWndProcOld);
}
void __declspec(dllexport) Select(HWND hwndParent, int string_size, TCHAR *variables, stack_t **stacktop, extra_parameters *extra)
{
Init(hwndParent, string_size, variables, stacktop, extra);
if (g_hwStartMenuSelect)
{
popstring(buf);
Show(hwndParent, string_size, variables, stacktop);
}
}
static BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL bRes = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam);
if (message == WM_NOTIFY_OUTER_NEXT && !bRes)
{
// if leave function didn't abort (lRes != 0 in that case)
PostMessage(g_hwStartMenuSelect,WM_USER+666,wParam,0);
}
return bRes;
}
void AddRTLStyle(HWND hWnd, long dwStyle)
{
long s;
s = GetWindowLong(hWnd, GWL_STYLE);
SetWindowLong(hWnd, GWL_STYLE, s | dwStyle);
s = GetWindowLong(hWnd, GWL_EXSTYLE);
SetWindowLong(hWnd, GWL_EXSTYLE, s | WS_EX_RIGHT | WS_EX_RTLREADING);
}
#define ProgressiveSetWindowPos(hwWindow, x, cx, cy) \
MoveWindow( \
hwWindow, \
x, \
y_offset, \
cx, \
cy, \
FALSE \
); \
\
y_offset += cy + 3;
BOOL CALLBACK dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND hwLocation = GetDlgItem(hwndDlg, IDC_LOCATION);
HWND hwDirList = GetDlgItem(hwndDlg, IDC_DIRLIST);
HWND hwCheckBox = GetDlgItem(hwndDlg, IDC_CHECK);
switch (uMsg)
{
case WM_INITDIALOG:
{
HWND hwIcon;
HWND hwText;
RECT dialog_r, temp_r;
HFONT hFont = (HFONT) SendMessage(hwParent, WM_GETFONT, 0, 0);
int y_offset = 0;
int width, height;
int baseUnitY;
// Init dialog unit conversion
{
TEXTMETRIC tm;
HDC hDC;
hDC = GetDC(hwndDlg);
SelectObject(hDC, hFont);
GetTextMetrics(hDC, &tm);
baseUnitY = tm.tmHeight;
ReleaseDC(hwndDlg, hDC);
}
GetWindowRect(hwChild, &dialog_r);
ScreenToClient(hwParent, (LPPOINT) &dialog_r);
ScreenToClient(hwParent, ((LPPOINT) &dialog_r) + 1);
width = dialog_r.right - dialog_r.left;
height = dialog_r.bottom - dialog_r.top;
MoveWindow(
hwndDlg,
dialog_r.left,
dialog_r.top,
width,
height,
FALSE
);
hwIcon = GetDlgItem(hwndDlg, IDC_NSISICON);
hwText = GetDlgItem(hwndDlg, IDC_TEXT);
g_hwDirList = hwDirList;
SendMessage(hwndDlg, WM_SETFONT, (WPARAM) hFont, TRUE);
SendMessage(hwIcon, WM_SETFONT, (WPARAM) hFont, TRUE);
SendMessage(hwText, WM_SETFONT, (WPARAM) hFont, TRUE);
SendMessage(hwLocation, WM_SETFONT, (WPARAM) hFont, TRUE);
SendMessage(hwDirList, WM_SETFONT, (WPARAM) hFont, TRUE);
SendMessage(hwCheckBox, WM_SETFONT, (WPARAM) hFont, TRUE);
if (rtl)
{
AddRTLStyle(hwText, SS_RIGHT);
AddRTLStyle(hwLocation, ES_RIGHT);
AddRTLStyle(hwDirList, 0);
AddRTLStyle(hwCheckBox, BS_RIGHT | BS_LEFTTEXT);
}
GetClientRect(hwIcon, &temp_r);
if (!noicon)
{
SendMessage(
hwIcon,
STM_SETIMAGE,
IMAGE_ICON,
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(103))
);
MoveWindow(
hwIcon,
rtl ? width - temp_r.right : 0,
0,
temp_r.right,
temp_r.bottom,
FALSE
);
temp_r.right += 3;
}
else
{
ShowWindow(hwIcon, SW_HIDE);
temp_r.right = 0;
}
if (rtl)
{
ProgressiveSetWindowPos(
hwText,
0,
width - temp_r.right,
3 * baseUnitY //MulDiv(24, baseUnitY, 8);
);
}
else
{
ProgressiveSetWindowPos(
hwText,
temp_r.right,
width - temp_r.right + 3,
3 * baseUnitY //MulDiv(24, baseUnitY, 8);
);
}
SetWindowText(hwText, *text ? text : _T("Select the Start Menu folder in which you would like to create the program's shortcuts:"));
ProgressiveSetWindowPos(
hwLocation,
0,
width,
MulDiv(12, baseUnitY, 8)
);
if (*lastused == _T('>'))
{
CheckDlgButton(hwndDlg, IDC_CHECK, BST_CHECKED);
lstrcpy(lastused, lstrcpy(buf, lastused) + 1);
EnableWindow(hwDirList, FALSE);
EnableWindow(hwLocation, FALSE);
}
SetWindowText(hwLocation, *lastused ? lastused : progname);
temp_r.bottom = MulDiv(8, baseUnitY, 8);
ProgressiveSetWindowPos(
hwDirList,
0,
width,
height - y_offset - (*checkbox ? temp_r.bottom + 3 : 0)
);
if (*checkbox)
{
ProgressiveSetWindowPos(
hwCheckBox,
0,
width,
temp_r.bottom
);
ShowWindow(hwCheckBox, SW_SHOWNA);
SetWindowText(hwCheckBox, checkbox);
}
AddFolderFromReg(CSIDL_COMMON_PROGRAMS);
AddFolderFromReg(CSIDL_PROGRAMS);
// Tell NSIS to remove old inner dialog and pass handle of the new inner dialog
SendMessage(hwParent, WM_NOTIFY_CUSTOM_READY, (WPARAM)hwndDlg, 0);
ShowWindow(hwndDlg, SW_SHOWNA);
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK) == BST_CHECKED)
SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwCheckBox, TRUE);
else
SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwLocation, TRUE);
}
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_DIRLIST && HIWORD(wParam) == LBN_SELCHANGE)
{
SendMessage(hwDirList, LB_GETTEXT, SendMessage(hwDirList, LB_GETCURSEL, 0, 0), (WPARAM)buf);
if (autoadd)
lstrcat(lstrcat(buf, _T("\\")), progname);
SetWindowText(hwLocation, buf);
}
else if (LOWORD(wParam) == IDC_CHECK && HIWORD(wParam) == BN_CLICKED)
{
BOOL bEnable = IsDlgButtonChecked(hwndDlg, IDC_CHECK) != BST_CHECKED;
EnableWindow(hwDirList, bEnable);
EnableWindow(hwLocation, bEnable);
}
else if (LOWORD(wParam) == IDC_LOCATION && HIWORD(wParam) == EN_CHANGE)
{
GetWindowText(hwLocation, buf, MAX_PATH);
validate_filename(buf);
EnableWindow(GetDlgItem(hwParent, IDOK), *buf != _T('\0'));
}
break;
case WM_USER+666:
g_done = 1;
if (wParam == NOTIFY_BYE_BYE)
pushstring(_T("cancel"));
else
{
GetWindowText(hwLocation, buf + 1, MAX_PATH);
validate_filename(buf);
if (IsDlgButtonChecked(hwndDlg, IDC_CHECK) == BST_CHECKED)
{
buf[0] = _T('>');
pushstring(buf);
}
else
{
pushstring(buf + 1);
}
pushstring(_T("success"));
}
case WM_CTLCOLORSTATIC:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORDLG:
case WM_CTLCOLORBTN:
case WM_CTLCOLORLISTBOX:
// let the NSIS window handle colors, it knows best
return SendMessage(hwParent, uMsg, wParam, lParam);
break;
}
return 0;
}
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
g_hInstance=hInst;
return TRUE;
}
void AddFolderFromReg(int nFolder)
{
//DWORD idx;
WIN32_FIND_DATA FileData;
HANDLE hSearch;
LPITEMIDLIST ppidl;
buf[0] = 0;
if (SHGetSpecialFolderLocation(hwParent, nFolder, &ppidl) == S_OK)
{
SHGetPathFromIDList(ppidl, buf);
CoTaskMemFree(ppidl);
}
if (!buf[0])
return;
lstrcat(buf, _T("\\*.*"));
hSearch = FindFirstFile(buf, &FileData);
if (hSearch != INVALID_HANDLE_VALUE)
{
do
{
if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (*(WORD*)FileData.cFileName != *(WORD*)_T("."))
{
if (*(WORD*)FileData.cFileName != *(WORD*)_T("..") || FileData.cFileName[2])
{
if (SendMessage(g_hwDirList, LB_FINDSTRINGEXACT, (WPARAM) -1, (LPARAM)FileData.cFileName) == LB_ERR)
SendMessage(g_hwDirList, LB_ADDSTRING, 0, (LPARAM)FileData.cFileName);
/*idx = */
/*SendMessage(hwDirList, LB_SETITEMDATA, (WPARAM)idx,
(LPARAM)ExtractAssociatedIcon(g_hInstance, FileData.cFileName, (WORD*)&idx));*/
}
}
}
} while (FindNextFile(hSearch, &FileData));
FindClose(hSearch);
}
}