diff options
| -rw-r--r-- | Makefile.mingw | 7 | ||||
| -rw-r--r-- | Makefile.mingw-amd64 | 7 | ||||
| -rw-r--r-- | Makefile.vc6 | 5 | ||||
| -rw-r--r-- | Makefile.vc6-ansi | 5 | ||||
| -rw-r--r-- | alf/alf.cpp | 25 | ||||
| -rw-r--r-- | alf/alf.h | 45 | ||||
| -rw-r--r-- | alf/alfcompat.cpp | 14 | ||||
| -rw-r--r-- | alf/alfcompat.h | 7 | ||||
| -rw-r--r-- | alf/alfmessagedlg.cpp | 438 | ||||
| -rw-r--r-- | widgetfactory.cpp | 44 |
10 files changed, 591 insertions, 6 deletions
diff --git a/Makefile.mingw b/Makefile.mingw index 5b8fe5d..def3fa3 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -8,7 +8,7 @@ LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static all: out/widgetfactory.exe out/alf/alf.c out/widgetfactory-c.exe -out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcombobox.o out/alfcompat.o out/alfcontrol.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alfgroupbox.o out/alficon.o out/alflabel.o out/alflayout.o out/alfnativebtn.o out/alfnotebook.o out/alfpanel.o out/alftoplevel.o +out/widgetfactory.exe: out/widgetfactory.o out/alfbutton.o out/alfcombobox.o out/alfcompat.o out/alfcontrol.o out/alf.o out/alfdpiaware.o out/alfedit.o out/alfgroupbox.o out/alficon.o out/alflabel.o out/alflayout.o out/alfmessagedlg.o out/alfnativebtn.o out/alfnotebook.o out/alfpanel.o out/alftoplevel.o $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) out/alfbutton.o: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -44,6 +44,9 @@ out/alflabel.o: alf/alflabel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/ out/alflayout.o: alf/alflayout.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< +out/alfmessagedlg.o: alf/alfmessagedlg.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CXXFLAGS) -c -o $@ $< + out/alfnativebtn.o: alf/alfnativebtn.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< @@ -59,7 +62,7 @@ out/alftoplevel.o: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alflayout. out/widgetfactory.o: widgetfactory.cpp alf/alf.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alftoplevel.cpp +out/alf/alf.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfmessagedlg.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alftoplevel.cpp @mkdir -p out/alf @printf "#include \"alf.h\"\\n" > $@ @cat $^ | grep -v "^#pragma once" | grep -v "^#include \"alf" >> $@ diff --git a/Makefile.mingw-amd64 b/Makefile.mingw-amd64 index 2ad5eb8..57b79c4 100644 --- a/Makefile.mingw-amd64 +++ b/Makefile.mingw-amd64 @@ -8,7 +8,7 @@ LDFLAGS = -luser32 -lcomctl32 -lshell32 -lversion -static all: out/widgetfactory64.exe out/alf/alf64.c out/widgetfactory64-c.exe -out/widgetfactory64.exe: out/widgetfactory.amd64.o out/alfbutton.amd64.o out/alfcombobox.amd64.o out/alfcompat.amd64.o out/alfcontrol.amd64.o out/alf.amd64.o out/alfdpiaware.amd64.o out/alfedit.amd64.o out/alfgroupbox.amd64.o out/alficon.amd64.o out/alflabel.amd64.o out/alflayout.amd64.o out/alfnativebtn.amd64.o out/alfnotebook.amd64.o out/alfpanel.amd64.o out/alftoplevel.amd64.o +out/widgetfactory64.exe: out/widgetfactory.amd64.o out/alfbutton.amd64.o out/alfcombobox.amd64.o out/alfcompat.amd64.o out/alfcontrol.amd64.o out/alf.amd64.o out/alfdpiaware.amd64.o out/alfedit.amd64.o out/alfgroupbox.amd64.o out/alficon.amd64.o out/alflabel.amd64.o out/alflayout.amd64.o out/alfmessagedlg.amd64.o out/alfnativebtn.amd64.o out/alfnotebook.amd64.o out/alfpanel.amd64.o out/alftoplevel.amd64.o $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) out/alfbutton.amd64.o: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -44,6 +44,9 @@ out/alflabel.amd64.o: alf/alflabel.cpp alf/alfcompat.h alf/alf.h alf/alflayout. out/alflayout.amd64.o: alf/alflayout.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< +out/alfmessagedlg.amd64.o: alf/alfmessagedlg.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CXXFLAGS) -c -o $@ $< + out/alfnativebtn.amd64.o: alf/alfnativebtn.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CXXFLAGS) -c -o $@ $< @@ -59,7 +62,7 @@ out/alftoplevel.amd64.o: alf/alftoplevel.cpp alf/alfcompat.h alf/alf.h alf/alfl out/widgetfactory.amd64.o: widgetfactory.cpp alf/alf.h $(CXX) $(CXXFLAGS) -c -o $@ $< -out/alf/alf64.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alftoplevel.cpp +out/alf/alf64.c: alf/alflist.h alf/alflayout.h alf/alfcompat.h alf/alfpriv.h alf/alfbutton.cpp alf/alfcombobox.cpp alf/alfcompat.cpp alf/alfcontrol.cpp alf/alf.cpp alf/alfdpiaware.cpp alf/alfedit.cpp alf/alfgroupbox.cpp alf/alficon.cpp alf/alflabel.cpp alf/alflayout.cpp alf/alfmessagedlg.cpp alf/alfnativebtn.cpp alf/alfnotebook.cpp alf/alfpanel.cpp alf/alftoplevel.cpp @mkdir -p out/alf @printf "#include \"alf.h\"\\n" > $@ @cat $^ | grep -v "^#pragma once" | grep -v "^#include \"alf" >> $@ diff --git a/Makefile.vc6 b/Makefile.vc6 index fad4fa0..635e5eb 100644 --- a/Makefile.vc6 +++ b/Makefile.vc6 @@ -4,7 +4,7 @@ CXX = cl.exe CFLAGS = -O2 -GA -W3 -DUNICODE -D_UNICODE -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo LDFLAGS = /link unicows.lib kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib -out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alftoplevel.obj +out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfmessagedlg.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alftoplevel.obj $(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS) out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -40,6 +40,9 @@ out/alflabel.obj: alf/alflabel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h al out/alflayout.obj: alf/alflayout.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alflayout.cpp +out/alfmessagedlg.obj: alf/alfmessagedlg.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alfmessagedlg.cpp + out/alfnativebtn.obj: alf/alfnativebtn.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfnativebtn.cpp diff --git a/Makefile.vc6-ansi b/Makefile.vc6-ansi index 8d534e6..174532f 100644 --- a/Makefile.vc6-ansi +++ b/Makefile.vc6-ansi @@ -4,7 +4,7 @@ CXX = cl.exe CFLAGS = -O2 -GA -W3 -D_WIN32=0x0501 -D_WIN32_WINNT=0x0501 -D_WIN32_IE=0x0501 -nologo LDFLAGS = /link /entry:_entry /opt:nowin98 /fixed:no kernel32.lib user32.lib comctl32.lib shell32.lib gdi32.lib version.lib -out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alftoplevel.obj +out/widgetfactory.exe: out/widgetfactory.obj out/alfbutton.obj out/alfcombobox.obj out/alfcompat.obj out/alfcontrol.obj out/alf.obj out/alfdpiaware.obj out/alfedit.obj out/alfgroupbox.obj out/alficon.obj out/alflabel.obj out/alflayout.obj out/alfmessagedlg.obj out/alfnativebtn.obj out/alfnotebook.obj out/alfpanel.obj out/alftoplevel.obj $(CXX) $(CFLAGS) -Fe$@ $** $(LDFLAGS) out/alfbutton.obj: alf/alfbutton.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h @@ -40,6 +40,9 @@ out/alflabel.obj: alf/alflabel.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h al out/alflayout.obj: alf/alflayout.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alflayout.cpp +out/alfmessagedlg.obj: alf/alfmessagedlg.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h + $(CXX) $(CFLAGS) -c -Fo$@ alf/alfmessagedlg.cpp + out/alfnativebtn.obj: alf/alfnativebtn.cpp alf/alfcompat.h alf/alf.h alf/alflayout.h alf/alflist.h alf/alfpriv.h $(CXX) $(CFLAGS) -c -Fo$@ alf/alfnativebtn.cpp diff --git a/alf/alf.cpp b/alf/alf.cpp index 1bcbce3..c2f99ce 100644 --- a/alf/alf.cpp +++ b/alf/alf.cpp @@ -75,6 +75,31 @@ ALF_Free(const void *p) HeapFree(GetProcessHeap(), 0, (void*)p); } +TCHAR * +ALF_StrDup(const TCHAR *psz) +{ + int l = lstrlen(psz); + TCHAR *r = ALF_New(TCHAR, (SIZE_T)l + 1); + CopyMemory(r, psz, ((SIZE_T)l + 1) * sizeof(TCHAR)); + return r; +} + +TCHAR * +ALF_StrOrIntresourceDup(const TCHAR *psz) +{ + if (IS_INTRESOURCE(psz)) + return (TCHAR *)psz; + else + return ALF_StrDup(psz); +} + +void +ALF_StrOrIntresourceFree(const TCHAR *psz) +{ + if (!IS_INTRESOURCE(psz)) + ALF_Free(psz); +} + int ALF_CentipointsToPixels(int cptValue, int dpi) { @@ -160,6 +160,15 @@ ALF_ReAlloc(void *ptr, SIZE_T nmemb, SIZE_T size); void ALF_Free(const void *p); +TCHAR * +ALF_StrDup(const TCHAR *psz); + +TCHAR * +ALF_StrOrIntresourceDup(const TCHAR *psz); + +void +ALF_StrOrIntresourceFree(const TCHAR *psz); + COLORREF ALF_ColorToGdi(ALFColor color); @@ -611,6 +620,42 @@ ALF_LoadIcon(HINSTANCE hinst, const TCHAR *name, int cx, int cy); SIZE ALF_IconSize(HICON icon); +// custom message box +HWND +ALF_MessageDlg_Create(HWND owner); + +void +ALF_MessageDlg_SetCaption(HWND msg, const TCHAR *caption); + +void +ALF_MessageDlg_SetText(HWND msg, const TCHAR *text); + +void +ALF_MessageDlg_SetIcon(HWND msg, HINSTANCE hinst, const TCHAR *name); + +void +ALF_MessageDlg_AddButton(HWND msg, WORD id, const TCHAR *text); + +WORD +ALF_MessageDlg_Run(HWND msg); + +// message box shortcuts +void +ALF_MessageDlg_Error(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText); + +void +ALF_MessageDlg_Warning(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText); + +void +ALF_MessageDlg_Information(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText); + +WORD // IDOK or IDCANCEL +ALF_MessageDlg_Confirm(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText, const TCHAR *cancelBtnText); + +// like ALF_MessageDlg_Confirm, but shows an exclamation icon and preselects the cancel button +WORD +ALF_MessageDlg_ConfirmDanger(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText, const TCHAR *cancelBtnText); + #ifdef __cplusplus } // extern C diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp index 31c3eaa..f5bed22 100644 --- a/alf/alfcompat.cpp +++ b/alf/alfcompat.cpp @@ -533,6 +533,17 @@ static HMONITOR WINAPI ALF_Compat_fallbackMonitorFromWindow(HWND window, DWORD f return (HMONITOR)0x12340042; // like multimon.h } +static BOOL WINAPI +ALF_Compat_fallbackSetDialogDpiChangeBehavior(HWND hDlg, + ALF_Compat_DIALOG_DPI_CHANGE_BEHAVIORS mask, + ALF_Compat_DIALOG_DPI_CHANGE_BEHAVIORS values) +{ + (void)hDlg; (void)mask; (void)values; + + SetLastError(ERROR_NOT_SUPPORTED); + return FALSE; +} + static BOOL CALLBACK ALF_Compat_DrawDisabledText_DrawStateProc(HDC hdc, @@ -647,6 +658,7 @@ void ALF_LoadCompatFunctions(void) LOAD_FUNC(user32, GetMonitorInfoA); LOAD_FUNC(user32, MonitorFromPoint); LOAD_FUNC(user32, MonitorFromWindow); + LOAD_FUNC(user32, SetDialogDpiChangeBehavior); *((FARPROC*)&ALF_Compat_TrackMouseEvent) = GetProcAddress(_alf_dll_comctl32, "_TrackMouseEvent"); if (!ALF_Compat_TrackMouseEvent) @@ -767,6 +779,7 @@ void ALF_UnloadCompatFunctions(void) UNLOAD_FUNC(GetThemeColor); UNLOAD_FUNC(GetThemeMargins); UNLOAD_FUNC(LoadIconWithScaleDown); + UNLOAD_FUNC(SetDialogDpiChangeBehavior); FreeLibrary(_alf_dll_uxtheme); FreeLibrary(_alf_dll_user32); @@ -808,3 +821,4 @@ HRESULT (WINAPI *ALF_Compat_LoadIconWithScaleDown)(HINSTANCE,PCWSTR,int,int,HICO BOOL (WINAPI *ALF_Compat_GetMonitorInfoA)(HMONITOR,MONITORINFO *) = NULL; HMONITOR (WINAPI *ALF_Compat_MonitorFromPoint)(POINT,DWORD) = NULL; HMONITOR (WINAPI *ALF_Compat_MonitorFromWindow)(HWND,DWORD) = NULL; +BOOL (WINAPI *ALF_Compat_SetDialogDpiChangeBehavior)(HWND, ALF_Compat_DIALOG_DPI_CHANGE_BEHAVIORS, ALF_Compat_DIALOG_DPI_CHANGE_BEHAVIORS) = NULL; diff --git a/alf/alfcompat.h b/alf/alfcompat.h index 8acdbc6..8f6b80f 100644 --- a/alf/alfcompat.h +++ b/alf/alfcompat.h @@ -86,6 +86,12 @@ typedef struct { int cyBottomHeight; } ALF_Compat_MARGINS; +typedef enum { + ALF_Compat_DDC_DEFAULT, + ALF_Compat_DDC_DISABLE_ALL, + ALF_Compat_DDC_DISABLE_RESIZE, + ALF_Compat_DDC_DISABLE_CONTROL_RELAYOUT +} ALF_Compat_DIALOG_DPI_CHANGE_BEHAVIORS; #ifndef TMT_TRANSITIONDURATION #define TMT_TRANSITIONDURATION 6000 @@ -141,6 +147,7 @@ extern HRESULT (WINAPI *ALF_Compat_LoadIconWithScaleDown)(HINSTANCE,PCWSTR,int,i extern BOOL (WINAPI *ALF_Compat_GetMonitorInfoA)(HMONITOR,MONITORINFO *); extern HMONITOR (WINAPI *ALF_Compat_MonitorFromPoint)(POINT,DWORD); extern HMONITOR (WINAPI *ALF_Compat_MonitorFromWindow)(HWND,DWORD); +extern BOOL (WINAPI *ALF_Compat_SetDialogDpiChangeBehavior)(HWND, ALF_Compat_DIALOG_DPI_CHANGE_BEHAVIORS, ALF_Compat_DIALOG_DPI_CHANGE_BEHAVIORS); // compatibility bits diff --git a/alf/alfmessagedlg.cpp b/alf/alfmessagedlg.cpp new file mode 100644 index 0000000..554d55d --- /dev/null +++ b/alf/alfmessagedlg.cpp @@ -0,0 +1,438 @@ +#include "alfpriv.h" + +#define ALF_WM_MESSAGEDLG_SETCAPTION (ALF_WM_USER + 1) +#define ALF_WM_MESSAGEDLG_SETTEXT (ALF_WM_USER + 2) +#define ALF_WM_MESSAGEDLG_ADDBUTTON (ALF_WM_USER + 3) +#define ALF_WM_MESSAGEDLG_SETICON (ALF_WM_USER + 4) +#define ALF_WM_MESSAGEDLG_BEEP (ALF_WM_USER + 5) + +typedef struct { + HINSTANCE hIconInstance; + PCTSTR pszIconName; + HWND hwndIconView; + HWND hwndIconWrapper; + HWND hwndText; + HWND hwndTextWrapper; + int nButtons; +} ALFMessageDlgPriv; + +static BOOL +ALF_MessageDlg_Initialize(void *closure, HWND hwnd) +{ + ALFMessageDlgPriv *priv = (ALFMessageDlgPriv *)closure; + + priv->hwndIconWrapper = ALF_AddPanel(hwnd, (WORD)-1, 0, 0); + priv->hwndTextWrapper = ALF_AddPanel(hwnd, (WORD)-1, 1, 0); + priv->hwndIconView = ALF_AddIconView(priv->hwndIconWrapper, (WORD)-1, 1, 1, NULL); + priv->hwndText = ALF_AddLabel(priv->hwndTextWrapper, (WORD)-1, 0, 1, TEXT("")); + + ALF_SetBackgroundColor(priv->hwndIconWrapper, ALF_COLOR_SYS(COLOR_WINDOW)); + ALF_SetBackgroundColor(priv->hwndTextWrapper, ALF_COLOR_SYS(COLOR_WINDOW)); + + ALF_SetTextColor(priv->hwndText, ALF_COLOR_SYS(COLOR_WINDOWTEXT)); + ALF_Label_SetStyle(priv->hwndText, ALF_LABEL_ALIGN_LEFT | ALF_LABEL_ALIGN_VCENTER); + + ALF_Layout_SetColumnMinSize(priv->hwndIconWrapper, 0, 1650); + ALF_Layout_SetColumnMinSize(priv->hwndIconWrapper, 2, 825); + ALF_Layout_SetRowMinSize(priv->hwndIconWrapper, 0, 1650); + ALF_Layout_SetRowMinSize(priv->hwndIconWrapper, 2, 1650); + ALF_Layout_SetRowExpandNumerator(priv->hwndIconWrapper, 2, 1); + ALF_Layout_SetColumnExpandNumerator(priv->hwndIconWrapper, 1, 1); + + ALF_Layout_SetColumnMinSize(priv->hwndTextWrapper, 1, 1650); + ALF_Layout_SetRowMinSize(priv->hwndTextWrapper, 0, 1650); + ALF_Layout_SetRowMinSize(priv->hwndTextWrapper, 2, 1650); + ALF_Layout_SetColumnExpandNumerator(priv->hwndTextWrapper, 1, 1); + ALF_Layout_SetRowExpandNumerator(priv->hwndTextWrapper, 2, 1); + ALF_Layout_SetRowFlags(priv->hwndTextWrapper, 1, ALF_LAYOUT_SIZE_PX); + + ALF_Layout_SetRowMinSize(hwnd, 1, 825); + ALF_Layout_SetRowMinSize(hwnd, 3, 825); + ALF_Layout_SetRowExpandNumerator(hwnd, 0, 1); + ALF_Layout_SetColumnExpandNumerator(hwnd, 1, 1); + + return FALSE; +} + +static void +ALF_MessageDlg_HandleAddButton(ALFMessageDlgPriv *priv, HWND hwnd, WORD id, const TCHAR *text) +{ + (void)hwnd; + + HWND hwndBtn = ALF_AddNativeButton(hwnd, id, 2 * priv->nButtons + 2, 2, text); + ALF_Layout_SetColumnMinSize(hwnd, 2 * priv->nButtons + 3, 525); + ALF_Layout_SetControlSpan(hwnd, priv->hwndTextWrapper, priv->nButtons * 2 + 3, 1); + + if (priv->nButtons == 0) + ALF_SetFocus(hwndBtn); + + priv->nButtons += 1; +} + +static void +ALF_MessageDlg_Destroy(void *closure, HWND hwnd) +{ + (void)hwnd; + ALFMessageDlgPriv *priv = (ALFMessageDlgPriv *)closure; + + HICON hicon = ALF_IconView_Icon(priv->hwndIconView); + DestroyIcon(hicon); +} + +static void +ALF_MessageDlg_PostDestroy(void *closure) +{ + ALFMessageDlgPriv *priv = (ALFMessageDlgPriv *)closure; + + ALF_StrOrIntresourceFree(priv->pszIconName); + ALF_Free(priv); +} + +static void +ALF_MessageDlg_UpdateIcon(ALFMessageDlgPriv *priv, HWND hwnd) +{ + UINT dpi = (UINT)ALF_GetDpi(hwnd); + HICON n = ALF_LoadIcon(priv->hIconInstance, priv->pszIconName, + ALF_Compat_GetSystemMetricsForDpi(SM_CXICON, dpi), + ALF_Compat_GetSystemMetricsForDpi(SM_CYICON, dpi)); + HICON o = ALF_IconView_SetIcon(priv->hwndIconView, n); + DestroyIcon(o); + + SIZE s = { 0, 0 }; + SendMessage(priv->hwndIconView, ALF_WM_QUERYSIZE, 0, (LPARAM)&s); + ALF_Layout_SetRowMinSize(priv->hwndTextWrapper, 1, s.cy); +} + +static void +ALF_MessageDlg_HandleFontsDpiChange(void *closure, HWND hwnd) +{ + ALFMessageDlgPriv *priv = (ALFMessageDlgPriv *)closure; + + ALF_MessageDlg_UpdateIcon(priv, hwnd); + ALF_Toplevel_SetDefaultFont(hwnd); +} + +static LRESULT +ALF_MessageDlg_HandleCommand(void *closure, HWND hwnd, WORD code, WORD sourceid, HWND control) +{ + (void)closure; + + if (control && code == BN_CLICKED) { + ALF_Toplevel_SetModalResult(hwnd, sourceid); + return 1; + } + + return 0; +} + +static void +ALF_MessageDlg_HandleSetIcon(ALFMessageDlgPriv *priv, HWND hwnd, HINSTANCE inst, const TCHAR *iconName) +{ + priv->hIconInstance = inst; + ALF_StrOrIntresourceFree(priv->pszIconName); + priv->pszIconName = ALF_StrOrIntresourceDup(iconName); + + ALF_MessageDlg_UpdateIcon(priv, hwnd); +} + +static void +ALF_MessageDlg_HandleSetCaption(ALFMessageDlgPriv *priv, HWND hwnd, const TCHAR *caption) +{ + (void)priv; + + ALF_SetText(hwnd, caption); +} + +static void +ALF_MessageDlg_HandleSetText(ALFMessageDlgPriv *priv, HWND hwnd, const TCHAR *text) +{ + (void)hwnd; + ALF_SetText(priv->hwndText, text); +} + +static void +ALF_MessageDlg_HandleBeep(ALFMessageDlgPriv *priv, HWND hwnd) +{ + (void)hwnd; + + if (priv->hIconInstance == NULL && priv->pszIconName == IDI_EXCLAMATION) + MessageBeep(MB_ICONEXCLAMATION); + else if (priv->hIconInstance == NULL && priv->pszIconName == IDI_HAND) + MessageBeep(MB_ICONHAND); + else if (priv->hIconInstance == NULL && priv->pszIconName == IDI_QUESTION) + MessageBeep(MB_ICONQUESTION); + else + MessageBeep(MB_ICONASTERISK); +} + +static LRESULT +ALF_MessageDlg_HandleWindowPosChanging(ALFMessageDlgPriv *priv, HWND hwnd, WPARAM wparam, WINDOWPOS *wp) +{ + (void)priv; + + // XXX: for WS_THICKFRAME windows this is done automatically, but we need to do it ourselves + // investigate whether it should be done in ALFToplevel + if (!(wp->flags & SWP_NOSIZE)) { + MINMAXINFO tmp = { + { 0, 0 }, + { wp->cx, wp->cy}, + { 0, 0 }, + { wp->cx, wp->cy }, + { wp->cx, wp->cy } + }; + SendMessage(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&tmp); + + if (tmp.ptMinTrackSize.x > wp->cx) + wp->cx = tmp.ptMinTrackSize.x; + + if (tmp.ptMinTrackSize.y > wp->cy) + wp->cy = tmp.ptMinTrackSize.y; + } + + return ALF_Toplevel_DefWindowProc(hwnd, WM_WINDOWPOSCHANGING, wparam, (LPARAM)wp); +} + +static int +ALF_MessageDlg_AsTextLength(ALFMessageDlgPriv *priv, HWND hwnd) +{ + int l = 0; + + int titlelength = GetWindowTextLength(hwnd); + + l += titlelength; + l += 2; //\r\n + l += titlelength; // underline + l += 4; //\r\n\r\n + l += GetWindowTextLength(priv->hwndText); + l += 4; //\r\n\r\n + + for (int i = 0; i < priv->nButtons; ++i) { + l += GetWindowTextLength(ALF_Layout_ControlAtPosition(hwnd, i * 2 + 2, 2)); + l += 3; // [] <space> or \r + } + + l += 1; // \n + return l; +} + +static void +ALF_MessageDlg_AsText(ALFMessageDlgPriv *priv, HWND hwnd, TCHAR *buf) +{ + int titlelength = GetWindowText(hwnd, buf, 0x7fffffff); + buf += titlelength; + *buf++ = '\r'; *buf++ = '\n'; + + for (int i = 0; i < titlelength; ++i) + *buf++ = '='; + + *buf++ = '\r'; *buf++ = '\n'; *buf++ = '\r'; *buf++ = '\n'; + buf += GetWindowText(priv->hwndText, buf, 0x7fffffff); + *buf++ = '\r'; *buf++ = '\n'; *buf++ = '\r'; *buf++ = '\n'; + for (int i = 0; i < priv->nButtons; ++i) { + if (i != 0) + *buf++ = ' '; + + *buf++ = '['; + buf += GetWindowText(ALF_Layout_ControlAtPosition(hwnd, i * 2 + 2, 2), buf, 0x7fffffff); + *buf++ = ']'; + } + + *buf++ = '\r'; *buf++ = '\n'; + *buf = 0; +} + +static BOOL +ALF_MessageDlg_PreTranslateMessage(void *closure, HWND hwnd, MSG *msg) +{ + ALFMessageDlgPriv *priv = (ALFMessageDlgPriv *)closure; + + if (msg->message == WM_KEYDOWN && (msg->wParam == VK_ESCAPE || msg->wParam == VK_CANCEL)) { + ALF_Toplevel_SetModalResult(hwnd, IDCANCEL); + return TRUE; + } else if (msg->message == WM_KEYDOWN && msg->wParam == 'C' && GetKeyState(VK_CONTROL) & 0x8000) { + if (OpenClipboard(hwnd)) { + EmptyClipboard(); + + int len = ALF_MessageDlg_AsTextLength(priv, hwnd); + + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, ((SIZE_T)len+1)*sizeof(TCHAR)); + TCHAR *buf = (TCHAR* )GlobalLock(hMem); + ALF_MessageDlg_AsText(priv, hwnd, buf); + GlobalUnlock(hMem); + +#ifdef UNICODE + SetClipboardData(CF_UNICODETEXT, hMem); +#else + SetClipboardData(CF_TEXT, hMem); +#endif + + CloseClipboard(); + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } +} + +static LRESULT +ALF_MessageDlg_HandleMessage(void *closure, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + ALFMessageDlgPriv *priv = (ALFMessageDlgPriv *)closure; + + switch (msg) { + case ALF_WM_MESSAGEDLG_SETCAPTION: + ALF_MessageDlg_HandleSetCaption(priv, hwnd, (const TCHAR *)lparam); + return 1; + case ALF_WM_MESSAGEDLG_SETTEXT: + ALF_MessageDlg_HandleSetText(priv, hwnd, (const TCHAR *)lparam); + return 1; + case ALF_WM_MESSAGEDLG_ADDBUTTON: + ALF_MessageDlg_HandleAddButton(priv, hwnd, (WORD)wparam, (const TCHAR *)lparam); + return 1; + case ALF_WM_MESSAGEDLG_SETICON: + ALF_MessageDlg_HandleSetIcon(priv, hwnd, (HINSTANCE)wparam, (const TCHAR *)lparam); + return 1; + case ALF_WM_MESSAGEDLG_BEEP: + ALF_MessageDlg_HandleBeep(priv, hwnd); + return 1; + case WM_WINDOWPOSCHANGING: + return ALF_MessageDlg_HandleWindowPosChanging(priv, hwnd, wparam, (WINDOWPOS *)lparam); + } + + return ALF_Toplevel_DefWindowProc(hwnd, msg, wparam, lparam); +} + +static void +ALF_MessageDlg_HandleClose(void *closure, HWND hwnd) +{ + (void)closure; + + ALF_Toplevel_SetModalResult(hwnd, IDCANCEL); +} + +static ALFToplevelVTable _alf_messageDlgVtbl = { + ALF_MessageDlg_Initialize, /* initialize */ + ALF_MessageDlg_Destroy, /* destroy */ + ALF_MessageDlg_HandleClose, /* close */ + ALF_MessageDlg_PostDestroy, /* postdestroy */ + ALF_MessageDlg_HandleMessage, /* message */ + ALF_MessageDlg_HandleCommand, /* command */ + NULL, /* notify */ + ALF_MessageDlg_PreTranslateMessage, /* pretranslatemessage */ + NULL, /* paint */ + NULL, /* windowposchanged */ + ALF_MessageDlg_HandleFontsDpiChange /* updatefontsdpi */ +}; + +HWND +ALF_MessageDlg_Create(HWND owner) +{ + ALFMessageDlgPriv *priv = ALF_New(ALFMessageDlgPriv, 1); + return ALF_CreateToplevelWindow(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE, + WS_POPUPWINDOW | WS_DLGFRAME | WS_CAPTION | DS_MODALFRAME, + owner, NULL, + &_alf_messageDlgVtbl, + priv); +} + +void +ALF_MessageDlg_SetCaption(HWND msg, const TCHAR *caption) +{ + SendMessage(msg, ALF_WM_MESSAGEDLG_SETCAPTION, 0, (LPARAM)caption); +} + +void +ALF_MessageDlg_SetText(HWND msg, const TCHAR *text) +{ + SendMessage(msg, ALF_WM_MESSAGEDLG_SETTEXT, 0, (LPARAM)text); +} + +void +ALF_MessageDlg_SetIcon(HWND msg, HINSTANCE hinst, const TCHAR *name) +{ + SendMessage(msg, ALF_WM_MESSAGEDLG_SETICON, (WPARAM)hinst, (LPARAM)name); +} + +void +ALF_MessageDlg_AddButton(HWND msg, WORD id, const TCHAR *text) +{ + SendMessage(msg, ALF_WM_MESSAGEDLG_ADDBUTTON, (WPARAM)id, (LPARAM)text); +} + +WORD +ALF_MessageDlg_Run(HWND msg) +{ + ALF_Toplevel_CenterOnOwnerMonitor(msg); + SendMessage(msg, ALF_WM_MESSAGEDLG_BEEP, 0, 0); + return (WORD)ALF_Toplevel_ShowModal(msg); +} + +// message box shortcuts +void +ALF_MessageDlg_Error(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText) +{ + HWND m = ALF_MessageDlg_Create(owner); + ALF_MessageDlg_SetCaption(m, caption); + ALF_MessageDlg_SetText(m, text); + ALF_MessageDlg_SetIcon(m, NULL, IDI_HAND); + ALF_MessageDlg_AddButton(m, IDOK, okBtnText ? okBtnText : TEXT("OK")); + ALF_MessageDlg_Run(m); + DestroyWindow(m); +} + +void +ALF_MessageDlg_Warning(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText) +{ + HWND m = ALF_MessageDlg_Create(owner); + ALF_MessageDlg_SetCaption(m, caption); + ALF_MessageDlg_SetText(m, text); + ALF_MessageDlg_SetIcon(m, NULL, IDI_EXCLAMATION); + ALF_MessageDlg_AddButton(m, IDOK, okBtnText ? okBtnText : TEXT("OK")); + ALF_MessageDlg_Run(m); + DestroyWindow(m); +} + +void +ALF_MessageDlg_Information(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText) +{ + HWND m = ALF_MessageDlg_Create(owner); + ALF_MessageDlg_SetCaption(m, caption); + ALF_MessageDlg_SetText(m, text); + ALF_MessageDlg_SetIcon(m, NULL, IDI_ASTERISK); + ALF_MessageDlg_AddButton(m, IDOK, okBtnText ? okBtnText : TEXT("OK")); + ALF_MessageDlg_Run(m); + DestroyWindow(m); +} + +WORD // IDOK or IDCANCEL +ALF_MessageDlg_Confirm(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText, const TCHAR *cancelBtnText) +{ + HWND m = ALF_MessageDlg_Create(owner); + ALF_MessageDlg_SetCaption(m, caption); + ALF_MessageDlg_SetText(m, text); + ALF_MessageDlg_SetIcon(m, NULL, IDI_QUESTION); + ALF_MessageDlg_AddButton(m, IDOK, okBtnText ? okBtnText : TEXT("OK")); + ALF_MessageDlg_AddButton(m, IDCANCEL, cancelBtnText ? cancelBtnText : TEXT("Cancel")); + WORD r = ALF_MessageDlg_Run(m); + DestroyWindow(m); + return r; +} + +// like ALF_MessageDlg_Confirm, but shows an exclamation icon and preselects the cancel button +WORD +ALF_MessageDlg_ConfirmDanger(HWND owner, const TCHAR *text, const TCHAR *caption, const TCHAR *okBtnText, const TCHAR *cancelBtnText) +{ + HWND m = ALF_MessageDlg_Create(owner); + ALF_MessageDlg_SetCaption(m, caption); + ALF_MessageDlg_SetText(m, text); + ALF_MessageDlg_SetIcon(m, NULL, IDI_EXCLAMATION); + ALF_MessageDlg_AddButton(m, IDOK, okBtnText ? okBtnText : TEXT("OK")); + ALF_MessageDlg_AddButton(m, IDCANCEL, cancelBtnText ? cancelBtnText : TEXT("Cancel")); + ALF_Toplevel_SetDefaultButton(m, IDCANCEL); + ALF_SetFocus(ALF_ControlHwndById(m, IDCANCEL)); + WORD r = ALF_MessageDlg_Run(m); + DestroyWindow(m); + return r; +} diff --git a/widgetfactory.cpp b/widgetfactory.cpp index cc3ede9..3298d81 100644 --- a/widgetfactory.cpp +++ b/widgetfactory.cpp @@ -40,6 +40,11 @@ enum { IDM_BACKGROUND_GREEN, IDM_BACKGROUND_BLUE, IDM_CENTER_ON_MONITOR, + IDM_MESSAGEDLG_INFO, + IDM_MESSAGEDLG_WARNING, + IDM_MESSAGEDLG_ERROR, + IDM_MESSAGEDLG_QUESTION, + IDM_MESSAGEDLG_DANGERQUESTION, IDM_PANES, IDM_PANES__MAX = IDM_PANES + PANE__MAX, IDM_MODALDIALOG_PANES, @@ -898,6 +903,39 @@ handleCommand(void *closure, HWND window, WORD notificationcode, WORD sourceid, ALF_Toplevel_CenterOnCurrentMonitor(window); } + if (sourceid == IDM_MESSAGEDLG_INFO) { + const TCHAR *text = TEXT("Hello World!\r\n\r\n" + "This is a really long text to show that there is no automatic line breaking going on.\r\n" + "We also want to demo\r\n\r\n\r\n\r\n\r\n\r\n" + "what happens when the text is very high"); + + ALF_MessageDlg_Information(window, text, TEXT("Hello"), NULL); + } + + if (sourceid == IDM_MESSAGEDLG_WARNING) { + ALF_MessageDlg_Warning(window, TEXT("Something noteworthy happened"), TEXT("Warning"), TEXT("Got it!")); + } + + if (sourceid == IDM_MESSAGEDLG_ERROR) { + ALF_MessageDlg_Error(window, TEXT("Something happened."), TEXT("ERROR"), NULL); + } + + if (sourceid == IDM_MESSAGEDLG_QUESTION) { + if (ALF_MessageDlg_Confirm(window, TEXT("Continue?"), TEXT("Question"), TEXT("Yes"), TEXT("No")) == IDOK) { + ALF_MessageDlg_Information(window, TEXT("You clicked OK"), TEXT("Info"), NULL); + } else { + ALF_MessageDlg_Information(window, TEXT("You clicked Cancel"), TEXT("Info"), NULL); + } + } + + if (sourceid == IDM_MESSAGEDLG_DANGERQUESTION) { + if (ALF_MessageDlg_ConfirmDanger(window, TEXT("Do you want to format your hard drive?"), TEXT("Question"), TEXT("&Format Drive"), TEXT("Cancel")) == IDOK) { + ALF_MessageDlg_Information(window, TEXT("You clicked OK"), TEXT("Info"), NULL); + } else { + ALF_MessageDlg_Information(window, TEXT("You clicked Cancel"), TEXT("Info"), NULL); + } + } + return 0; } @@ -1090,6 +1128,12 @@ WinMain AppendMenu(helpmenu, MF_STRING, IDM_CENTER_ON_MONITOR, TEXT("Center Window")); AppendMenu(helpmenu, MF_SEPARATOR, 0, 0); + AppendMenu(helpmenu, MF_STRING, IDM_MESSAGEDLG_INFO, TEXT("Information")); + AppendMenu(helpmenu, MF_STRING, IDM_MESSAGEDLG_WARNING, TEXT("Warning")); + AppendMenu(helpmenu, MF_STRING, IDM_MESSAGEDLG_ERROR, TEXT("Error")); + AppendMenu(helpmenu, MF_STRING, IDM_MESSAGEDLG_QUESTION, TEXT("Question")); + AppendMenu(helpmenu, MF_STRING, IDM_MESSAGEDLG_DANGERQUESTION, TEXT("Dangerous Question")); + AppendMenu(helpmenu, MF_SEPARATOR, 0, 0); AppendMenu(helpmenu, MF_STRING, IDM_HELP_ABOUT, TEXT("&About")); AppendMenu(bgmenu, MF_STRING, IDM_BACKGROUND_INHERIT, TEXT("(Default)")); |
