NSIS/Contrib/nsDialogs/nsDialogs.c
kichik b163ed1dc4 CreateItem -> CreateControl
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@5239 212acab6-be3b-0410-9dea-997c60f758d6
2007-08-17 16:37:04 +00:00

409 lines
9.4 KiB
C

#include <windows.h>
#include "defs.h"
#include "nsis.h"
#include "input.h"
#include "rtl.h"
HINSTANCE g_hInstance;
struct nsDialog g_dialog;
extra_parameters* g_pluginParms;
struct nsControl* NSDFUNC GetControl(HWND hwCtl)
{
unsigned id = (unsigned) GetProp(hwCtl, NSCONTROL_ID_PROP);
if (id == 0 || id > g_dialog.controlCount)
{
return NULL;
}
return &g_dialog.controls[id - 1];
}
BOOL CALLBACK ParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL res;
if (message == WM_NOTIFY_OUTER_NEXT)
{
if (wParam == (WPARAM)-1)
{
if (g_pluginParms->ExecuteCodeSegment(g_dialog.callbacks.onBack - 1, 0))
{
return 0;
}
}
}
res = CallWindowProc(g_dialog.parentOriginalWndproc, hwnd, message, wParam, lParam);
if (message == WM_NOTIFY_OUTER_NEXT && !res)
{
DestroyWindow(g_dialog.hwDialog);
HeapFree(GetProcessHeap(), 0, g_dialog.controls);
g_dialog.hwDialog = NULL;
g_dialog.controls = NULL;
}
return res;
}
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
// handle notifications
case WM_COMMAND:
{
HWND hwCtl = GetDlgItem(hwndDlg, LOWORD(wParam));
struct nsControl* ctl = GetControl(hwCtl);
if (ctl == NULL)
break;
if (HIWORD(wParam) == BN_CLICKED && ctl->type == NSCTL_BUTTON)
{
pushint((int) hwCtl);
g_pluginParms->ExecuteCodeSegment(ctl->callbacks.onClick - 1, 0);
}
else if (HIWORD(wParam) == EN_CHANGE && ctl->type == NSCTL_EDIT)
{
pushint((int) hwCtl);
g_pluginParms->ExecuteCodeSegment(ctl->callbacks.onChange - 1, 0);
}
else if (HIWORD(wParam) == LBN_SELCHANGE && ctl->type == NSCTL_LISTBOX)
{
pushint((int) hwCtl);
g_pluginParms->ExecuteCodeSegment(ctl->callbacks.onChange - 1, 0);
}
else if (HIWORD(wParam) == CBN_SELCHANGE && ctl->type == NSCTL_COMBOBOX)
{
pushint((int) hwCtl);
g_pluginParms->ExecuteCodeSegment(ctl->callbacks.onChange - 1, 0);
}
break;
}
case WM_NOTIFY:
{
LPNMHDR nmhdr = (LPNMHDR) lParam;
struct nsControl* ctl = GetControl(nmhdr->hwndFrom);
if (ctl == NULL)
break;
if (!ctl->callbacks.onNotify)
break;
pushint((int) nmhdr);
pushint(nmhdr->code);
pushint((int) nmhdr->hwndFrom);
g_pluginParms->ExecuteCodeSegment(ctl->callbacks.onNotify - 1, 0);
}
// handle colors
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(g_dialog.hwParent, uMsg, wParam, lParam);
}
return FALSE;
}
void __declspec(dllexport) Create(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
HWND hwPlacementRect;
RECT rcPlacement;
EXDLL_INIT();
g_dialog.hwParent = hwndParent;
g_pluginParms = extra;
hwPlacementRect = GetDlgItem(hwndParent, popint());
GetWindowRect(hwPlacementRect, &rcPlacement);
MapWindowPoints(NULL, hwndParent, (LPPOINT) &rcPlacement, 2);
g_dialog.hwDialog = CreateDialog(g_hInstance, MAKEINTRESOURCE(1), hwndParent, DialogProc);
SetWindowPos(
g_dialog.hwDialog,
0,
rcPlacement.left,
rcPlacement.top,
rcPlacement.right - rcPlacement.left,
rcPlacement.bottom - rcPlacement.top,
SWP_NOZORDER | SWP_NOACTIVATE
);
g_dialog.parentOriginalWndproc = (WNDPROC) SetWindowLong(hwndParent, DWL_DLGPROC, (long) ParentProc);
g_dialog.rtl = FALSE;
g_dialog.controlCount = 0;
g_dialog.controls = (struct nsControl*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 0);
pushint((int) g_dialog.hwDialog);
}
void __declspec(dllexport) CreateControl(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
char *className;
char *text;
HWND hwItem;
int x, y, width, height;
DWORD style, exStyle;
size_t id;
// get info from stack
className = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, g_stringsize * 2);
text = &className[g_stringsize];
if (!className)
return;
if (popstring(className, 0))
{
HeapFree(GetProcessHeap(), 0, className);
return;
}
style = (DWORD) popint();
exStyle = (DWORD) popint();
PopPlacement(&x, &y, &width, &height);
if (popstring(text, 0))
{
HeapFree(GetProcessHeap(), 0, className);
return;
}
// create item descriptor
id = g_dialog.controlCount;
g_dialog.controlCount++;
g_dialog.controls = (struct nsControl*) HeapReAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
g_dialog.controls,
g_dialog.controlCount * sizeof(struct nsControl));
if (!lstrcmpi(className, "BUTTON"))
g_dialog.controls[id].type = NSCTL_BUTTON;
else if (!lstrcmpi(className, "EDIT"))
g_dialog.controls[id].type = NSCTL_EDIT;
else if (!lstrcmpi(className, "COMBOBOX"))
g_dialog.controls[id].type = NSCTL_COMBOBOX;
else if (!lstrcmpi(className, "LISTBOX"))
g_dialog.controls[id].type = NSCTL_LISTBOX;
else if (!lstrcmpi(className, "RichEdit"))
g_dialog.controls[id].type = NSCTL_RICHEDIT;
else if (!lstrcmpi(className, "RICHEDIT_CLASS"))
g_dialog.controls[id].type = NSCTL_RICHEDIT2;
else if (!lstrcmpi(className, "STATIC"))
g_dialog.controls[id].type = NSCTL_STATIC;
else
g_dialog.controls[id].type = NSCTL_UNKNOWN;
// apply rtl to style
ConvertStyleToRTL(g_dialog.controls[id].type, &style, &exStyle);
// create item's window
hwItem = CreateWindowEx(
exStyle,
className,
text,
style,
x, y, width, height,
g_dialog.hwDialog,
(HMENU) (1200 + id),
g_hInstance,
NULL);
g_dialog.controls[id].window = hwItem;
// remember id
SetProp(hwItem, NSCONTROL_ID_PROP, (HANDLE) (id + 1));
// set font
SendMessage(hwItem, WM_SETFONT, SendMessage(g_dialog.hwParent, WM_GETFONT, 0, 0), TRUE);
// push back result
pushint((int) hwItem);
// done
HeapFree(GetProcessHeap(), 0, className);
}
// for backward compatibility (2.29 had CreateItem)
void __declspec(dllexport) CreateItem(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
CreateControl(hwndParent, string_size, variables, stacktop, extra);
}
void __declspec(dllexport) SetUserData(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
HWND hwCtl;
struct nsControl* ctl;
// get info from stack
hwCtl = (HWND) popint();
if (!IsWindow(hwCtl))
{
popint(); // remove user data from stack
return;
}
// get descriptor
ctl = GetControl(hwCtl);
if (ctl == NULL)
return;
// set user data
popstring(ctl->userData, USERDATA_SIZE);
}
void __declspec(dllexport) GetUserData(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
HWND hwCtl;
struct nsControl* ctl;
// get info from stack
hwCtl = (HWND) popint();
if (!IsWindow(hwCtl))
{
pushstring("");
return;
}
// get descriptor
ctl = GetControl(hwCtl);
if (ctl == NULL)
{
pushstring("");
return;
}
// return user data
pushstring(ctl->userData);
}
void NSDFUNC SetControlCallback(size_t callbackIdx)
{
HWND hwCtl;
nsFunction callback;
nsFunction* callbacks;
struct nsControl* ctl;
// get info from stack
hwCtl = (HWND) popint();
callback = (nsFunction) popint();
if (!IsWindow(hwCtl))
return;
// get descriptor
ctl = GetControl(hwCtl);
if (ctl == NULL)
return;
// set callback
callbacks = (nsFunction*) &ctl->callbacks;
callbacks[callbackIdx] = callback;
}
void NSDFUNC SetDialogCallback(size_t callbackIdx)
{
nsFunction callback;
nsFunction* callbacks;
// get info from stack
callback = (nsFunction) popint();
// set callback
callbacks = (nsFunction*) &g_dialog.callbacks;
callbacks[callbackIdx] = callback;
}
void __declspec(dllexport) OnClick(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
SetControlCallback(CTL_CALLBACK_IDX(onClick));
}
void __declspec(dllexport) OnChange(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
SetControlCallback(CTL_CALLBACK_IDX(onChange));
}
void __declspec(dllexport) OnNotify(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
SetControlCallback(CTL_CALLBACK_IDX(onNotify));
}
void __declspec(dllexport) OnBack(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
SetDialogCallback(DLG_CALLBACK_IDX(onBack));
}
void __declspec(dllexport) Show(HWND hwndParent, int string_size, char *variables, stack_t **stacktop, extra_parameters *extra)
{
// tell NSIS to remove old inner dialog and pass handle of the new inner dialog
SendMessage(hwndParent, WM_NOTIFY_CUSTOM_READY, (WPARAM) g_dialog.hwDialog, 0);
ShowWindow(g_dialog.hwDialog, SW_SHOWNA);
// message loop
while (g_dialog.hwDialog)
{
MSG msg;
GetMessage(&msg, NULL, 0, 0);
if (!IsDialogMessage(g_dialog.hwDialog, &msg) && !IsDialogMessage(g_dialog.hwParent, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// reset wndproc
SetWindowLong(hwndParent, DWL_DLGPROC, (long) g_dialog.parentOriginalWndproc);
}
BOOL WINAPI DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
{
g_hInstance = (HINSTANCE) hInst;
return TRUE;
}