#pragma once #define WIN32_LEAN_AND_MEAN #include #ifdef __cplusplus extern "C" { #endif typedef struct { BOOL (*initialize)(void * /*closure*/, HWND /*window*/); // return FALSE if you set the focus, TRUE if you want default initial focus void (*destroy)(void * /*closure*/, HWND /*window*/); void (*close)(void * /*closure*/, HWND /*window*/); void (*postdestroy)(void * /*closure*/); LRESULT (*message)(void * /*closure*/, HWND, UINT, WPARAM, LPARAM); LRESULT (*command)(void * /*closure*/, HWND /*window*/, WORD /*notificationcode*/, WORD /*sourceid*/, HWND /*control*/); LRESULT (*notify)(void * /*closure*/, HWND /*window*/, WPARAM /*sourceid*/, NMHDR *); BOOL (*pretranslatemessage)(void * /*closure*/, HWND /*window*/, MSG * /*message*/); void (*paint)(void * /*closure*/, HWND, HDC, RECT *); void (*windowposchanged)(void * /*closure*/, HWND, WINDOWPOS *); } ALFToplevelVTable; typedef struct { void (*attachvtbl)(void * /*closure*/, HWND /*panel*/); void (*destroy)(void * /*closure*/, HWND /*panel*/); LRESULT (*message)(void * /*closure*/, HWND, UINT, WPARAM, LPARAM); LRESULT (*command)(void * /*closure*/, HWND /*window*/, WORD /*notificationcode*/, WORD /*sourceid*/, HWND /*control*/); LRESULT (*notify)(void * /*closure*/, HWND /*window*/, WPARAM /*sourceid*/, NMHDR *); void (*paint)(void * /*closure*/, HWND, HDC, RECT * /*rcPaint*/); void (*windowposchanged)(void * /*closure*/, HWND, WINDOWPOS *); } ALFPanelVTable; typedef struct { const ALFPanelVTable *vtbl; void *closure; } ALFPanelSetVtblParams; // layout flags #define ALF_LAYOUT_SIZE_FIXED 0x00 #define ALF_LAYOUT_SIZE_QUERY 0x01 #define ALF_LAYOUT_SIZE_PUSHBUTTON 0x04 #define ALF_LAYOUT_SIZE_STATICTEXT 0x05 /* unimplemented */ #define ALF_LAYOUT_SIZE_EDIT 0x06 #define ALF_LAYOUT_SIZE_RADIOBUTTON 0x07 #define ALF_LAYOUT_SIZE_CHECKBOX 0x07 #define ALF_LAYOUT_SIZETYPE_MASK 0x0f #define ALF_LAYOUT_INHERITFONT 0x10 #define ALF_LAYOUT_CUSTOMPOS 0x20 #define ALF_LAYOUT_SIZE_PX 0x40 #define ALF_LAYOUT_INHERITBGCOLOR 0x80 #define ALF_LAYOUT_TRANSPARENTBG 0x100 #define ALF_LAYOUT_SENDBGCHANGE 0x200 #define ALF_LAYOUT_SENDDPICHANGE 0x400 // label style flags #define ALF_LABEL_ALIGN_LEFT 0 #define ALF_LABEL_ALIGN_LEFT_LIKE_EDIT 1 #define ALF_LABEL_ALIGN_HCENTER 2 #define ALF_LABEL_ALIGN_RIGHT 3 #define ALF_LABEL_HALIGN_MASK 3 #define ALF_LABEL_ALIGN_TOP 0 #define ALF_LABEL_ALIGN_TOP_LIKE_EDIT 4 #define ALF_LABEL_ALIGN_VCENTER 8 #define ALF_LABEL_ALIGN_BOTTOM 12 #define ALF_LABEL_VALIGN_MASK 12 // notebook flags #define ALF_NOTEBOOK_SOLID_TAB_BACKGROUND 1 // messages #define ALF_WM__BASE 0x2800 #define ALF_WM_QUERYSIZE (ALF_WM__BASE + 1) #define ALF_WM_UPDATEFONTS (ALF_WM__BASE + 3) #define ALF_WM_ADDCONTROL (ALF_WM__BASE + 4) #define ALF_WM_CONTROLBYID (ALF_WM__BASE + 5) #define ALF_WM_REMOVECONTROL (ALF_WM__BASE + 6) #define ALF_WM_SETMODALRESULT (ALF_WM__BASE + 7) #define ALF_WM_GETMODALRESULT (ALF_WM__BASE + 8) #define ALF_WM_GETDPI (ALF_WM__BASE + 9) #define ALF_WM_GETAPPLICATION (ALF_WM__BASE + 10) #define ALF_WM_BACKGROUNDCHANGE (ALF_WM__BASE + 11) #define ALF_WM_APPLYSIZE (ALF_WM__BASE + 12) #define ALF_WM_SETBGCOLOR (ALF_WM__BASE + 13) #define ALF_WM_GETBGCOLOR (ALF_WM__BASE + 14) #define ALF_WM_LYT_GETCTLATPOS (ALF_WM__BASE + 15) #define ALF_WM_INVALIDATELAYOUT (ALF_WM__BASE + 17) #define ALF_WM_VALIDATELAYOUT (ALF_WM__BASE + 18) #define ALF_WM_LYT_GETCTLPOS (ALF_WM__BASE + 19) #define ALF_WM_LYT_SETCTLPOS (ALF_WM__BASE + 20) #define ALF_WM_LYT_GETCTLSIZE (ALF_WM__BASE + 21) #define ALF_WM_LYT_SETCTLSIZE (ALF_WM__BASE + 22) #define ALF_WM_LYT_GETCTLFLAGS (ALF_WM__BASE + 23) #define ALF_WM_LYT_SETCTLFLAGS (ALF_WM__BASE + 24) #define ALF_WM_LYT_GETCOLSIZE (ALF_WM__BASE + 25) #define ALF_WM_LYT_SETCOLSIZE (ALF_WM__BASE + 26) #define ALF_WM_LYT_GETCOLEXPAND (ALF_WM__BASE + 27) #define ALF_WM_LYT_SETCOLEXPAND (ALF_WM__BASE + 28) #define ALF_WM_LYT_GETCOLFLAGS (ALF_WM__BASE + 29) #define ALF_WM_LYT_SETCOLFLAGS (ALF_WM__BASE + 30) #define ALF_WM_LYT_GETROWSIZE (ALF_WM__BASE + 31) #define ALF_WM_LYT_SETROWSIZE (ALF_WM__BASE + 32) #define ALF_WM_LYT_GETROWEXPAND (ALF_WM__BASE + 33) #define ALF_WM_LYT_SETROWEXPAND (ALF_WM__BASE + 34) #define ALF_WM_LYT_GETROWFLAGS (ALF_WM__BASE + 35) #define ALF_WM_LYT_SETROWFLAGS (ALF_WM__BASE + 36) #define ALF_WM_GETTEXTCOLOR (ALF_WM__BASE + 37) #define ALF_WM_SETTEXTCOLOR (ALF_WM__BASE + 38) #define ALF_WM_DPICHANGE (ALF_WM__BASE + 39) #define ALF_WM_LYT_GETCTLSPAN (ALF_WM__BASE + 40) #define ALF_WM_LYT_SETCTLSPAN (ALF_WM__BASE + 41) #define ALF_WM_LBL_GETSTYLE (ALF_WM__BASE + 201) #define ALF_WM_LBL_SETSTYLE (ALF_WM__BASE + 202) #define ALF_WM_PANEL_SETVTABLE (ALF_WM__BASE + 201) #define ALF_WM_PANEL_GETEDGE (ALF_WM__BASE + 202) #define ALF_WM_PANEL_SETEDGE (ALF_WM__BASE + 203) #define ALF_WM_NTBK_GETFLAGS (ALF_WM__BASE + 201) #define ALF_WM_NTBK_SETFLAGS (ALF_WM__BASE + 202) #define ALF_WM_NTBK_ADDTAB (ALF_WM__BASE + 203) #define ALF_WM_NTBK_TABCOUNT (ALF_WM__BASE + 204) #define ALF_WM_NTBK_GETPANEL (ALF_WM__BASE + 205) #define ALF_WM_NTBK_GETSELINDEX (ALF_WM__BASE + 206) #define ALF_WM_NTBK_GETPNLINDEX (ALF_WM__BASE + 207) #define ALF_WM_USER (ALF_WM__BASE + 300) typedef DWORD ALFColor; #define ALF_COLOR_TRANSPARENT ((ALFColor)-1) #define ALF_COLOR_RGB(r, g, b) ((ALFColor)(((DWORD)(BYTE)r) | (((DWORD)(BYTE)g) << 8) | (((DWORD)(BYTE)b) << 16))) #define ALF_COLOR_SYS(i) ((ALFColor)(0x80000000 | (((DWORD)(BYTE)i) << 24))) typedef enum { ALF_DPI_AWARENESS_UNAWARE, ALF_DPI_AWARENESS_SYSTEM_AWARE, ALF_DPI_AWARENESS_PER_MONITOR_AWARE_V2 } ALFDpiAwareness; void ALF_SetDpiAwareness(ALFDpiAwareness awareness); void ALF_Initialize(void); void ALF_UnInitialize(void); void * ALF_Alloc(SIZE_T nmemb, SIZE_T size); void * ALF_ReAlloc(void *ptr, SIZE_T nmemb, SIZE_T size); #define ALF_New(type, count) ((type *)ALF_Alloc((count), sizeof(type))) #define ALF_ReNew(ptr, type, count) ((type *)ALF_ReAlloc(ptr, (count), sizeof(type))) void ALF_Free(const void *p); COLORREF ALF_ColorToGdi(ALFColor color); int ALF_CentipointsToPixels(int cptValue, int dpi); int ALF_GetDpi(HWND hwnd); HWND ALF_ControlHwndById(HWND win, WORD id); // Sends ALF_WM_BACKGROUNDCHANGE to notify the window of a changed background // Only useful when you have overridden the window or panel pain() vfunc // when you use solid background colors, ALF will handle this automatically void ALF_InvalidateBackground(HWND win); // Recalculates the window's fonts and applies them to child controls. // ALF does this automatically on a DPI or settings change so you shouldn't have // to call ALF_UpdateFonts(). void ALF_UpdateFonts(HWND win); // Sets the background color of the given window // Also, if the window is a child window, disables the ALF_LAYOUT_INHERITBGCOLOR flag // Only the following controls have background colors: // - Top-Level window // - Panel // - Label // TODO: button, ... void ALF_SetBackgroundColor(HWND win, ALFColor color); ALFColor ALF_BackgroundColor(HWND win); ALFColor ALF_TextColor(HWND win); void ALF_SetTextColor(HWND win, ALFColor color); void ALF_SetFocus(HWND target); void ALF_SetText(HWND hwnd, const TCHAR *text); TCHAR * // free with ALF_Free ALF_Text(HWND hwnd); void ALF_FillRect(HDC dc, const RECT *rc, ALFColor color); // wrapper for MessageBox() that handles modality for multiple toplevels with ALFApplication int ALF_MessageBox(HWND hwnd, const TCHAR *text, const TCHAR *caption, UINT type); // layout // // All of these functions are appropriate for every container that contains layouted children, // i.e. toplevel, panel and groupbox // // Container controls which do not layout their children (e.g. notebook) might still // support some of these functions in some ways, mostly (Set)ControlFlags so that // background color and font inheritance can be toggled void ALF_InvalidateLayout(HWND win); void ALF_AddControl(HWND win, int x, int y, HWND control, int width, int height, DWORD flags); DWORD ALF_Layout_ControlFlags(HWND parent, HWND control); BOOL ALF_Layout_SetControlFlags(HWND parent, HWND control, DWORD flags); static inline void ALF_Layout_AddControlFlag(HWND parent, HWND control, DWORD flag) { ALF_Layout_SetControlFlags(parent, control, ALF_Layout_ControlFlags(parent, control) | flag); } static inline void ALF_Layout_RemoveControlFlag(HWND parent, HWND control, DWORD flag) { ALF_Layout_SetControlFlags(parent, control, ALF_Layout_ControlFlags(parent, control) & ~flag); } BOOL ALF_Layout_ControlPosition(HWND parent, HWND control, int *pX, int *pY); BOOL ALF_Layout_SetControlPosition(HWND parent, HWND control, int x, int y); BOOL ALF_Layout_ControlSpan(HWND parent, HWND control, int *pXspan, int *pYspan); BOOL ALF_Layout_SetControlSpan(HWND parent, HWND control, int xspan, int yspan); BOOL ALF_Layout_ControlMinSize(HWND parent, HWND control, int *pWidth, int *pheight); BOOL ALF_Layout_SetControlMinSize(HWND parent, HWND control, int width, int height); HWND ALF_Layout_ControlAtPosition(HWND parent, int x, int y); int ALF_Layout_RowMinSize(HWND parent, int rowno); BOOL ALF_Layout_SetRowMinSize(HWND parent, int rowno, int rowsize); int ALF_Layout_ColumnMinSize(HWND parent, int colno); BOOL ALF_Layout_SetColumnMinSize(HWND parent, int colno, int colsize); DWORD ALF_Layout_RowFlags(HWND parent, int rowno); BOOL ALF_Layout_SetRowFlags(HWND parent, int rowno, DWORD flags); static inline BOOL ALF_Layout_AddRowFlag(HWND parent, int rowno, DWORD addflag) { return ALF_Layout_SetRowFlags(parent, rowno, ALF_Layout_RowFlags(parent, rowno) | addflag); } static inline BOOL ALF_Layout_RemoveRowFlag(HWND parent, int rowno, DWORD removeflag) { return ALF_Layout_SetRowFlags(parent, rowno, ALF_Layout_RowFlags(parent, rowno) & ~removeflag); } DWORD ALF_Layout_ColumnFlags(HWND parent, int colno); BOOL ALF_Layout_SetColumnFlags(HWND parent, int colno, DWORD flags); static inline BOOL ALF_Layout_AddColumnFlag(HWND parent, int colno, DWORD addflag) { return ALF_Layout_SetColumnFlags(parent, colno, ALF_Layout_ColumnFlags(parent, colno) | addflag); } static inline BOOL ALF_Layout_RemoveColumnFlag(HWND parent, int colno, DWORD removeflag) { return ALF_Layout_SetColumnFlags(parent, colno, ALF_Layout_ColumnFlags(parent, colno) & ~removeflag); } int ALF_Layout_RowExpandNumerator(HWND parent, int rowno); BOOL ALF_Layout_SetRowExpandNumerator(HWND parent, int rowno, int expand); int ALF_Layout_ColumnExpandNumerator(HWND parent, int colno); BOOL ALF_Layout_SetColumnExpandNumerator(HWND parent, int colno, int expand); // application // ALFApplication is a container for multiple top-level windows. // // Having an ALFApplication is not required, but it enables you to get modality // right in the face of multiple top-level windows. // // NOTE: ALFApplication is not thread-safe. It must be accessed only from the // thread that created it, and all toplevels associated with the application // must live on that same thread. There must be at most one application per thread. typedef struct tagALFApplication ALFApplication; ALFApplication * ALF_CreateApplication(void); void ALF_Application_ProcessMessages(ALFApplication *app); // continuously processes messages until a quit message is posted // or all windows have been destroyed void ALF_Application_Run(ALFApplication *app); BOOL ALF_Application_EnumToplevels(ALFApplication *app, WNDENUMPROC proc, LPARAM param); HWND ALF_Application_ActiveToplevel(ALFApplication *app); void ALF_Application_SetPreTranslateMessageHandler(ALFApplication *app, BOOL(*handler)(void *,MSG *), void *closure); BOOL ALF_Application_PreTranslateMessage(ALFApplication *app, MSG *msg, HWND modalToplevel); // Modality with multiple toplevels // -------------------------------- // // How it works: // * A "modal disable" counter is managed for each ALF toplevel // * Calling ALF_Application_DisableWindowsForModal() will increase the counter // for each toplevel of the application, except for the HWND skip // * Calling ALF_Application_ReenableWindowsForModal() will decrease the counter // for each toplevel of the application, except for the HWND skip // // How to show a modal ALF toplevel: // (1) It is assumed that we're running on the thread that owns the modal toplevel // (2) Show the modal toplevel // (3) If the modal has an ALFApplication: // (3.1) Call DisableWindowsForModal on that app with skip=modal // (4) Additionally, disable the owner with EnableWindow() // The owner might be a non-ALF window or live on another thread, in which // case it is not being disabled in step 3.1. // (5) Run the modal message loop // (6) Undo (4) via EnableWindow // (7) Undo (3.1) via EnableWindowsForModal with skip=modal // (8) Hide the modal window // --> see ALF_Toplevel_ShowModal() for an example of how to do this // // How to show a modal window that adheres to Win32 modality conventions: // (1) If the owner window lives on the same thread and has an ALFApplication: // (1.1) Call DisableWindowsForModal on that app with skip=owner // (2) Run the modal window // (3) undo 1.1 via EnableWindowsForModal with skip=owner // --> see ALF_MessageBox() for an example of how to do this void ALF_Application_DisableWindowsForModal(ALFApplication *app, HWND skip); void ALF_Application_ReenableWindowsForModal(ALFApplication *app, HWND skip); // also destroys all toplevels associated with the application void ALF_DestroyApplication(ALFApplication *app); // toplevel window // NOTE about app: If app==NULL, the owner's app will be copied if the owner lives on the same thread HWND ALF_CreateToplevelWindow(DWORD exstyle, DWORD style, HWND hwndOwner, ALFApplication *app, ALFToplevelVTable *vtbl, void *closure); ALFApplication * ALF_Toplevel_Application(HWND toplevel); void ALF_Toplevel_Resize(HWND win, int cptWidth, int cptHeight); void ALF_Toplevel_ResizePx(HWND win, int pxWidth, int pxHeight); // To add to your message loop like IsDialogMessage // NOT TREAD SAFE: Only call from the thread owning the window // (accesses internal data structures directly for performance) BOOL ALF_Toplevel_PreTranslateMessage(HWND toplevel, MSG *msg); // Shows the window as a modal window (i.e. disabling the owner window) // returns once the modal window has been ended via ALF_Toplevel_SetModalResult // NOT THREAD SAFE: Only call from the thread owning the window // (accesses internal data structures directly for performance) LPARAM ALF_Toplevel_ShowModal(HWND toplevel); void ALF_Toplevel_SetModalResult(HWND win, LRESULT result); LRESULT ALF_Toplevel_GetModalResult(HWND win); LRESULT ALF_Toplevel_DefWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); void ALF_Toplevel_EnsureBigEnough(HWND toplevel); // NOTE about default buttons: // // - If no default button is specified, the default button will be the button // with the id IDOK. A WM_COMMAND message on pressing the return key will be // sent even if no control with the default id can be found. // - In NT 3.51, the default button must be a direct child of the window. Otherwise // the default button effect will not work. // - In Win32s on Win3.1, the default button should be a direct child of the window. // Otherwise the default button effect will be buggy when setting the focus // via WM_NEXTDLGCTL or ALF_SetFocus(), but it will work correctly when using // the TAB key. // - Changing the default button will only fully take effect after a focus change. // It might temporarily lead to artifacts such as having two or no default buttons. // // Recommendation: Set the default button during window initialization, and then // immediately set the focus via ALF_SetFocus(). If you want to support NT 3.51 // or Win32s, ensure that the default button is a direct child of the toplevel window. void ALF_Toplevel_SetDefaultButton(HWND win, WORD id); // label HWND ALF_AddLabel(HWND win, WORD id, int x, int y, const TCHAR *text); DWORD ALF_Label_Style(HWND hwndLabel); void ALF_Label_SetStyle(HWND hwndLabel, DWORD style); // edit HWND ALF_AddEdit(HWND win, WORD id, int x, int y, const TCHAR *text); // button HWND ALF_AddButton(HWND win, WORD id, int x, int y, const TCHAR *text); // combo box HWND ALF_AddEditableComboBox(HWND win, WORD id, int x, int y, const TCHAR *defaultText); HWND ALF_AddSelectionOnlyComboBox(HWND win, WORD id, int x, int y); int /* index */ ALF_ComboBox_AddString(HWND combo, const TCHAR *text); void ALF_ComboBox_InsertString(HWND combo, int index, const TCHAR *text); void ALF_ComboBox_RemoveString(HWND combo, int index); TCHAR * // free with ALF_Free ALF_ComboBox_StringForIndex(HWND combo, int index); int ALF_ComboBox_CurrentIndex(HWND combo); void ALF_ComboBox_SetCurrentIndex(HWND combo, int index); TCHAR * // free with ALF_Free ALF_ComboBox_CurrentText(HWND combo); void ALF_ComboBox_SetText(HWND combo, const TCHAR *text); // panel HWND ALF_AddPanel(HWND parent, WORD id, int x, int y); void ALF_Panel_SetVTable(HWND panel, const ALFPanelVTable *vtbl, void *closure); LRESULT ALF_Panel_DefWindowProc(HWND panel, UINT msg, WPARAM wparam, LPARAM lparam); void ALF_Panel_DefPaint(HWND panel, HDC hDC, RECT *rcPaint); DWORD ALF_Panel_Edge(HWND panel); void ALF_Panel_SetEdge(HWND panel, DWORD edge); // tab control HWND ALF_AddNotebook(HWND parent, WORD id, int x, int y); HWND ALF_Notebook_AddTab(HWND notebook, const TCHAR *title); int ALF_Notebook_TabCount(HWND notebook); int ALF_Notebook_TabIndex(HWND notebook, HWND tabPanel); int ALF_Notebook_SelectedIndex(HWND notebook); HWND ALF_Notebook_SelectedPanel(HWND notebook); HWND ALF_Notebook_TabPanel(HWND notebook, int index); DWORD ALF_Notebook_Flags(HWND notebook); void ALF_Notebook_SetFlags(HWND notebook, DWORD flags); static inline void ALF_Notebook_AddFlag(HWND notebook, DWORD flag) { ALF_Notebook_SetFlags(notebook, ALF_Notebook_Flags(notebook) | flag); } static inline void ALF_Notebook_RemoveFlag(HWND notebook, DWORD flag) { ALF_Notebook_SetFlags(notebook, ALF_Notebook_Flags(notebook) & ~flag); } // checkbox HWND ALF_AddCheckbox(HWND parent, WORD id, int x, int y, const TCHAR *text); // radio HWND ALF_AddRadioButton(HWND parent, WORD id, int x, int y, const TCHAR *text); // groupbox HWND ALF_AddGroupBox(HWND parent, WORD id, int x, int y, const TCHAR *text); // native buttons HWND ALF_AddNativeButton(HWND win, WORD id, int x, int y, const TCHAR *text); HWND ALF_AddNativeCheckbox(HWND parent, WORD id, int x, int y, const TCHAR *text); HWND ALF_AddNativeRadioButton(HWND parent, WORD id, int x, int y, const TCHAR *text); #ifdef __cplusplus } // extern C #endif