Permalink
Browse files

Replaced dialog resources with control template

Also fixed tabbing in dialogs.
  • Loading branch information...
1 parent 37aee69 commit 3d6132811f01d1c31b3b8e648601853e02c1630e @poiru poiru committed Dec 13, 2012
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2012 Birunthan Mohanathas
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "ControlTemplate.h"
+
+namespace ControlTemplate
+{
+
+void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString)
+{
+ for (UINT i = 0; i < ctCount; ++i)
+ {
+ const Control& ct = cts[i];
+
+ WCHAR* text = ct.textId ? getString(ct.textId) : NULL;
+
+ RECT r = { ct.x, ct.y, ct.w, ct.h };
+ MapDialogRect(parent, &r);
+
+ HWND wnd = CreateWindowEx(
+ ct.exStyle,
+ ct.name,
+ text,
+ ct.style,
+ r.left, r.top, r.right, r.bottom,
+ parent,
+ (HMENU)ct.id,
+ NULL,
+ NULL);
+ SendMessage(wnd, WM_SETFONT, (WPARAM)font, FALSE);
+ }
+}
+
+} // namespace ControlTemplate
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2012 Birunthan Mohanathas
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RM_COMMON_CONTROLTEMPLATE_H_
+#define RM_COMMON_CONTROLTEMPLATE_H_
+
+#include <Windows.h>
+
+namespace ControlTemplate
+{
+
+struct Control
+{
+ const WCHAR* name;
+ WORD id;
+ WORD textId;
+ short x;
+ short y;
+ short w;
+ short h;
+ DWORD style;
+ DWORD exStyle;
+};
+
+typedef WCHAR* (*GetStringFunc)(UINT id);
+
+void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString);
+
+// Helpers to declare control structs.
+#define CT_ITEM(name, id, textId, x, y, w, h, style, exStyle) \
+ { name, id, textId, x, y, w, h, WS_CHILD | style, exStyle }
+
+#define CT_BUTTON(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"Button", id, textId, x, y, w, h, BS_PUSHBUTTON | style, exStyle)
+
+#define CT_CHECKBOX(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"Button", id, textId, x, y, w, h, BS_AUTOCHECKBOX | style, exStyle)
+
+#define CT_COMBOBOX(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"ComboBox", id, textId, x, y, w, h, style, exStyle)
+
+#define CT_EDIT(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"Edit", id, textId, x, y, w, h, ES_LEFT | style, exStyle)
+
+#define CT_GROUPBOX(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"Button", id, textId, x, y, w, h, BS_GROUPBOX | style, exStyle)
+
+#define CT_ICON(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ICON | style, exStyle)
+
+#define CT_LABEL(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"Static", id, textId, x, y, w, h, SS_LEFT | style, exStyle)
+
+#define CT_LINEH(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ETCHEDHORZ | style, exStyle)
+
+#define CT_LINKLABEL(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"SysLink", id, textId, x, y, w, h, style, exStyle)
+
+#define CT_LISTBOX(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"ListBox", id, textId, x, y, w, h, style, exStyle)
+
+#define CT_LISTVIEW(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"SysListView32", id, textId, x, y, w, h, style, exStyle)
+
+#define CT_TAB(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"SysTabControl32", id, textId, x, y, w, h, TCS_TABS | style, exStyle)
+
+#define CT_TREEVIEW(id, textId, x, y, w, h, style, exStyle) \
+ CT_ITEM(L"SysTreeView32", id, textId, x, y, w, h, style, exStyle)
+
+} // namespace ControlTemplate
+
+#endif
View
@@ -0,0 +1,254 @@
+/*
+ Copyright (C) 2012 Birunthan Mohanathas
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include "Dialog.h"
+#include <Commctrl.h>
+#include <Uxtheme.h>
+
+HWND CDialog::c_ActiveDialogWindow = NULL;
+
+//
+// CBaseDialog
+//
+
+CBaseDialog::CBaseDialog() :
+ m_Window()
+{
+}
+
+/*
+** Create (if not already) and show the dialog.
+**
+*/
+void CBaseDialog::Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent)
+{
+ if (m_Window)
+ {
+ // Show existing window.
+ ShowWindow(m_Window, SW_SHOW);
+ SetForegroundWindow(m_Window);
+ return;
+ }
+
+ const WCHAR* font = L"MS Shell Dlg 2";
+ const size_t titleSize = (wcslen(title) + 1) * sizeof(WCHAR);
+ const size_t fontSize = (wcslen(font) + 1) * sizeof(WCHAR);
+
+ const size_t dataSize = sizeof(DLGTEMPLATE) +
+ sizeof(WCHAR) + // Menu array.
+ sizeof(WCHAR) + // Class array.
+ titleSize + // Title array.
+ sizeof(WORD) + // Font point size.
+ fontSize; // Font array.
+
+ DLGTEMPLATE* dt = (DLGTEMPLATE*)new BYTE[dataSize];
+ dt->style = style | DS_SHELLFONT | WS_VISIBLE;
+ dt->dwExtendedStyle = exStyle;
+ dt->cdit = 0;
+ dt->x = x;
+ dt->y = y;
+ dt->cx = w;
+ dt->cy = h;
+
+ BYTE* dtExtra = (BYTE*)dt + sizeof(DLGTEMPLATE);
+
+ // Menu array.
+ *(WCHAR*)dtExtra = L'\0';
+ dtExtra += sizeof(WCHAR);
+
+ // Class array.
+ *(WCHAR*)dtExtra = L'\0';
+ dtExtra += sizeof(WCHAR);
+
+ // Title array.
+ memcpy(dtExtra, title, titleSize);
+ dtExtra += titleSize;
+
+ // Font point size.
+ *(WORD*)dtExtra = 8;
+ dtExtra += sizeof(WORD);
+
+ // Font array.
+ memcpy(dtExtra, font, fontSize);
+
+ CreateDialogIndirectParam(NULL, dt, parent, InitialDlgProc, (LPARAM)this);
+
+ delete [] dt;
+}
+
+void CBaseDialog::CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString)
+{
+ ControlTemplate::CreateControls(cts, ctCount, m_Window, font, getString);
+}
+
+INT_PTR CALLBACK CBaseDialog::InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == WM_INITDIALOG)
+ {
+ CBaseDialog* dialog = (CBaseDialog*)lParam;
+ dialog->m_Window = hWnd;
+ SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)dialog);
+ SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)MainDlgProc);
+ return dialog->HandleMessage(uMsg, wParam, lParam);
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK CBaseDialog::MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ CBaseDialog* dialog = (CBaseDialog*)GetWindowLongPtr(hWnd, DWLP_USER);
+ return dialog->HandleMessage(uMsg, wParam, lParam);
+}
+
+//
+// CDialog
+//
+
+CDialog::CDialog() : CBaseDialog(),
+ m_Font(),
+ m_FontBold()
+{
+ NONCLIENTMETRICS ncm;
+ ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
+ m_Font = CreateFontIndirect(&ncm.lfMenuFont);
+ ncm.lfMenuFont.lfWeight = FW_BOLD;
+ ncm.lfMenuFont.lfHeight -= 2;
+ m_FontBold = CreateFontIndirect(&ncm.lfMenuFont);
+}
+
+CDialog::~CDialog()
+{
+ DestroyWindow(m_Window);
+ DeleteObject(m_Font);
+ DeleteObject(m_FontBold);
+}
+
+void CDialog::ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent)
+{
+ Show(title, x, y, w, h, style, exStyle, parent);
+}
+
+INT_PTR CDialog::OnActivate(WPARAM wParam, LPARAM lParam)
+{
+ c_ActiveDialogWindow = wParam ? m_Window : NULL;
+ return FALSE;
+}
+
+bool CDialog::HandleMessage(MSG& msg)
+{
+ if (c_ActiveDialogWindow)
+ {
+ if (IsDialogMessage(c_ActiveDialogWindow, &msg))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+** Subclass button control to draw arrow on the right.
+**
+*/
+void CDialog::SetMenuButton(HWND button)
+{
+ SetWindowSubclass(button, MenuButtonProc, NULL, NULL);
+}
+
+LRESULT CALLBACK CDialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
+{
+ LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam);
+
+ switch (uMsg)
+ {
+ case WM_PAINT:
+ {
+ // Draw arrow on top of the button
+ RECT buttonRect;
+ GetClientRect(hWnd, &buttonRect);
+ int arrowX = buttonRect.right - 18;
+ int arrowY = buttonRect.top + 4;
+ RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 };
+
+ HDC dc = GetDC(hWnd);
+ const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented
+ DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE);
+ DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags);
+ ReleaseDC(hWnd, dc);
+ }
+ break;
+
+ case WM_GETTEXT:
+ {
+ // Append 3 spaces to the button text to move text to the left so
+ // that it looks better with BS_CENTER.
+ WCHAR* str = (WCHAR*)lParam + result;
+ str[0] = str[1] = str[2] = L' ';
+ str[3] = '\0';
+ result += 3;
+ }
+ break;
+
+ case WM_GETTEXTLENGTH:
+ result += 3;
+ break;
+
+ case WM_NCDESTROY:
+ RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass);
+ break;
+ }
+
+ return result;
+}
+
+//
+// CTab
+//
+
+CDialog::CTab::CTab() : CBaseDialog(),
+ m_Initialized(false)
+{
+}
+
+void CDialog::CTab::CreateTabWindow(short x, short y, short w, short h, HWND owner)
+{
+ const DWORD style = DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
+ const DWORD exStyle = WS_EX_CONTROLPARENT;
+ Show(L"", x, y, w, h, style, exStyle, owner);
+
+ EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB);
+}
+
+CDialog::CTab::~CTab()
+{
+ DestroyWindow(m_Window);
+}
+
+void CDialog::CTab::Activate()
+{
+ if (!m_Initialized)
+ {
+ Initialize();
+ }
+
+ EnableWindow(m_Window, TRUE);
+ BringWindowToTop(m_Window);
+}
Oops, something went wrong.

0 comments on commit 3d61328

Please sign in to comment.