diff options
author | Alexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de> | 2005-04-06 15:18:59 +0000 |
---|---|---|
committer | Alexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de> | 2005-04-06 15:18:59 +0000 |
commit | 6870f13c45a0300e598725b23cd613df522e234e (patch) | |
tree | f03b209c250750a8716536b4030b2e1823b34a64 |
First import of xlaunch frontend for Xming
-rwxr-xr-x | COPYING | 24 | ||||
-rwxr-xr-x | Makefile | 79 | ||||
-rw-r--r-- | config.cc | 278 | ||||
-rw-r--r-- | config.h | 56 | ||||
-rwxr-xr-x | main.cc | 668 | ||||
-rwxr-xr-x | resources/dialog.rc | 113 | ||||
-rwxr-xr-x | resources/fullscreen.bmp | bin | 0 -> 22554 bytes | |||
-rwxr-xr-x | resources/images.rc | 29 | ||||
-rwxr-xr-x | resources/multiwindow.bmp | bin | 0 -> 22554 bytes | |||
-rwxr-xr-x | resources/nodecoration.bmp | bin | 0 -> 22554 bytes | |||
-rwxr-xr-x | resources/resources.h | 91 | ||||
-rwxr-xr-x | resources/resources.rc | 30 | ||||
-rw-r--r-- | resources/strings.rc | 99 | ||||
-rwxr-xr-x | resources/windowed.bmp | bin | 0 -> 22554 bytes | |||
-rwxr-xr-x | window/dialog.cc | 86 | ||||
-rwxr-xr-x | window/dialog.h | 54 | ||||
-rw-r--r-- | window/util.cc | 1111 | ||||
-rw-r--r-- | window/util.h | 53 | ||||
-rwxr-xr-x | window/window.cc | 284 | ||||
-rwxr-xr-x | window/window.h | 114 | ||||
-rwxr-xr-x | window/wizard.cc | 243 | ||||
-rwxr-xr-x | window/wizard.h | 59 |
22 files changed, 3471 insertions, 0 deletions
@@ -0,0 +1,24 @@ + + Copyright (c) 2005 Alexander Gottwald + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name(s) of the above copyright + holders shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written authorization. diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..f7cf923 --- /dev/null +++ b/Makefile @@ -0,0 +1,79 @@ +# +# Copyright (c) 2005 Alexander Gottwald +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name(s) of the above copyright +# holders shall not be used in advertising or otherwise to promote the sale, +# use or other dealings in this Software without prior written authorization. +# +WINDRES=windres + +TARGET=mingw +#DEBUG_FLAGS=-D_DEBUG + +OS_FLAGS_mingw=-mno-cygwin +OS_FLAGS=$(OS_FLAGS_$(TARGET)) $(DEBUG_FLAGS) + +X11_DIR_$(TARGET)=/usr/X11R6 +X11_DIR_mingw=../../../../../exports +X11_DIR=$(X11_DIR_$(TARGET)) +X11_INCLUDE=-I$(X11_DIR)/include +X11_LIBDIR=-L$(X11_DIR)/lib +X11_LIBS_$(TARGET)=-lX11 +X11_LIBS_mingw=-lX11 -lwsock32 +X11_LIBS=$(X11_LIBS_$(TARGET)) + +PROGRAMFILES:=$(shell cygpath -u $(PROGRAMFILES)) +#MSXML_DIR=$(PROGRAMFILES)/MSXML 4.0 +MSXML_DIR=$(PROGRAMFILES)/Microsoft XML Parser SDK +MSXML_INCLUDE="-I$(MSXML_DIR)/inc" +MSXML_LIBDIR="-L$(MSXML_DIR)/lib" +MSXML_LIBS= + + +CXXFLAGS=-g $(OS_FLAGS) $(X11_INCLUDE) $(MSXML_INCLUDE) +LDFLAGS=-mwindows $(X11_LIBDIR) $(MSXML_LIBDIR) +LIBS=-lcomctl32 -lole32 -loleaut32 $(X11_LIBS) $(MSXML_LIBS) +all:xlaunch.exe +%.res: %.rc + $(WINDRES) -O coff -o $@ $< + +WINDOW_PARTS=window util dialog wizard +WINDOW_OBJECTS=$(foreach file,$(WINDOW_PARTS),window/$(file).o) + +RESOURCES_IMAGES=resources/multiwindow.bmp resources/fullscreen.bmp \ + resources/windowed.bmp resources/nodecoration.bmp + +resources/resources.res: resources/resources.rc resources/resources.h \ + resources/images.rc resources/dialog.rc resources/strings.rc \ + $(RESOURCES_IMAGES) +xlaunch.exe: $(WINDOW_OBJECTS) main.o config.o resources/resources.res + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + + +window/dialog.o: window/dialog.cc window/dialog.h window/window.h window/util.h +window/frame.o: window/frame.cc window/frame.h window/window.h +window/util.o: window/util.cc window/util.h +window/window.o: window/window.cc window/window.h window/util.h +window/wizard.o: window/wizard.cc window/wizard.h window/dialog.h \ + window/window.h window/util.h +main.o: main.cc window/util.h window/wizard.h window/dialog.h \ + window/window.h resources/resources.h config.h +config.o: config.cc config.h diff --git a/config.cc b/config.cc new file mode 100644 index 0000000..a70dd4f --- /dev/null +++ b/config.cc @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#include "config.h" +#include "window/util.h" +#include <msxml2.h> +#include <stdexcept> + +const CLSID CLSID_DOMDocument40 = {0x88d969c0,0xf192,0x11d4,0xa6,0x5f,0x00,0x40,0x96,0x32,0x51,0xe5}; +const CLSID CLSID_DOMDocument30 = {0xf5078f32,0xc551,0x11d3,0x89,0xb9,0x00,0x00,0xf8,0x1f,0xe2,0x21}; +const IID IID_IXMLDOMDocument2 = {0x2933BF95,0x7B36,0x11d2,0xB2,0x0E,0x00,0xC0,0x4F,0x98,0x3E,0x60}; + +#define HRCALL(x, msg) if (FAILED(x)) { throw std::runtime_error("OLE Error:" msg " failed"); }; + +char *wcconvert(const wchar_t *wstr) +{ + int chars = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL); + if (chars == 0) + throw win32_error("WideCharToMultiByte"); + char *mbstr = new char[chars]; + chars = WideCharToMultiByte(CP_ACP, 0, wstr, -1, mbstr, chars, NULL, NULL); + if (chars == 0) + throw win32_error("WideCharToMultiByte"); + return mbstr; +} + +wchar_t *mbconvert(const char *mbstr) +{ + int chars = MultiByteToWideChar(CP_ACP, 0, mbstr, -1, NULL, 0); + if (chars == 0) + throw win32_error("MultiByteToWideChar"); + wchar_t *wstr = new wchar_t[chars]; + chars = MultiByteToWideChar(CP_ACP, 0, mbstr, -1, wstr, chars); + if (chars == 0) + throw win32_error("MultiByteToWideChar"); + return wstr; +} + +VARIANT VariantString(const char *filename) +{ + + wchar_t *str = mbconvert(filename); + + VARIANT var; + VariantInit(&var); + V_BSTR(&var) = SysAllocString(str); + V_VT(&var) = VT_BSTR; + + delete [] str; + return var; +} + +VARIANT VariantString(const wchar_t *str) +{ + VARIANT var; + VariantInit(&var); + V_BSTR(&var) = SysAllocString(str); + V_VT(&var) = VT_BSTR; + return var; +} + +IXMLDOMDocument2 *CreateDocument() +{ + IXMLDOMDocument2 *doc = NULL; + + CoInitialize(NULL); + + HRCALL(CoCreateInstance(CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, + IID_IXMLDOMDocument2, (void**)&doc), "CoCreateInstance"); + + try { + HRCALL(doc->put_async(VARIANT_FALSE), "put_async"); + HRCALL(doc->put_validateOnParse(VARIANT_FALSE), "put_validateOnParse"); + HRCALL(doc->put_resolveExternals(VARIANT_FALSE), "put_resolveExternals"); + + IXMLDOMProcessingInstruction *pi = NULL; + IXMLDOMElement *root = NULL; + BSTR xml = SysAllocString(L"xml"); + BSTR ver = SysAllocString(L"version='1.0'"); + HRCALL(doc->createProcessingInstruction(xml,ver, &pi), + "createProcessingInstruction"); + HRCALL(doc->appendChild(pi, NULL), + "appendChild"); + pi->Release(); + SysFreeString(xml); + SysFreeString(ver); + + BSTR elemname = SysAllocString(L"XLaunch"); + HRCALL(doc->createElement(elemname, &root), "createElement"); + HRCALL(doc->appendChild(root, NULL), "appendChild"); + SysFreeString(elemname); + } catch (...) + { + doc->Release(); + throw; + } + return doc; +} + +void setAttribute(IXMLDOMElement *elem, const wchar_t *name, const wchar_t *value) +{ + BSTR str = SysAllocString(name); + VARIANT var = VariantString(value); + HRCALL(elem->setAttribute(str, var), "setAttribute"); + VariantClear(&var); + SysFreeString(str); +} + +void setAttribute(IXMLDOMElement *elem, const wchar_t *name, const char *value) +{ + wchar_t *wstr = mbconvert(value); + setAttribute(elem, name, wstr); + delete [] wstr; + return; +} + +void CConfig::Save(const char *filename) +{ + IXMLDOMDocument2 *doc = CreateDocument(); + IXMLDOMElement *root = NULL; + + HRCALL(doc->get_documentElement(&root), "get_documentElement"); + + switch (window) + { + case MultiWindow: + setAttribute(root, L"WindowMode", L"MultiWindow"); + break; + case Fullscreen: + setAttribute(root, L"WindowMode", L"Fullscreen"); + break; + default: + case Windowed: + setAttribute(root, L"WindowMode", L"Windowed"); + break; + case Nodecoration: + setAttribute(root, L"WindowMode", L"Nodecoration"); + break; + } + switch (client) + { + default: + case NoClient: + setAttribute(root, L"ClientMode", L"NoClient"); + break; + case StartProgram: + setAttribute(root, L"ClientMode", L"StartProgram"); + break; + case XDMCP: + setAttribute(root, L"ClientMode", L"XDMCP"); + break; + } + setAttribute(root, L"LocalClient", local?L"True":L"False"); + setAttribute(root, L"Display", display.c_str()); + setAttribute(root, L"Program", program.c_str()); + setAttribute(root, L"RemoteProtocol", protocol.c_str()); + setAttribute(root, L"RemoteHost", host.c_str()); + setAttribute(root, L"RemoteUser", user.c_str()); + setAttribute(root, L"XDMCPHost", xdmcp_host.c_str()); + setAttribute(root, L"XDMCPBroadcast", broadcast?L"True":L"False"); + setAttribute(root, L"XDMCPIndirect", indirect?L"True":L"False"); + + VARIANT var = VariantString(filename); + HRCALL(doc->save(var), "save"); + VariantClear(&var); + + + root->Release(); + doc->Release(); +} + +BOOL getAttribute(IXMLDOMElement *elem, const wchar_t *name, std::string &ret) +{ + VARIANT var; + HRCALL(elem->getAttribute((OLECHAR*)name, &var), "getAttribute"); + if (V_VT(&var) != VT_NULL && V_VT(&var) == VT_BSTR) + { + char *str = wcconvert(V_BSTR(&var)); + ret = str; + delete [] str; + return true; + } + return false; +} + +BOOL getAttributeBool(IXMLDOMElement *elem, const wchar_t *name, bool &ret) +{ + std::string str; + if (getAttribute(elem, name, str)) + { + if (str == "True") + ret = true; + else + ret = false; + return true; + } + return false; +} + + +void CConfig::Load(const char *filename) +{ + IXMLDOMDocument2 *doc = CreateDocument(); + IXMLDOMElement *root = NULL; + + VARIANT var = VariantString(filename); + VARIANT_BOOL status; + HRCALL(doc->load(var, &status), "load"); + VariantClear(&var); + + if (status == VARIANT_FALSE) + { + doc->Release(); + return; + } + + HRCALL(doc->get_documentElement(&root), "get_documentElement"); + + std::string windowMode; + std::string clientMode; + + if (getAttribute(root, L"WindowMode", windowMode)) + { + if (windowMode == "MultiWindow") + window = MultiWindow; + else if (windowMode == "Fullscreen") + window = Fullscreen; + else if (windowMode == "Windowed") + window = Windowed; + else if (windowMode == "Nodecoration") + window = Nodecoration; + } + if (getAttribute(root, L"ClientMode", clientMode)) + { + if (clientMode == "NoClient") + client = NoClient; + else if (clientMode == "StartProgram") + client = StartProgram; + else if (clientMode == "XDMCP") + client = XDMCP; + } + + getAttributeBool(root, L"LocalClient", local); + getAttribute(root, L"Display", display); + getAttribute(root, L"Program", program); + getAttribute(root, L"RemoteProtocol", protocol); + getAttribute(root, L"RemoteHost", host); + getAttribute(root, L"RemoteUser", user); + getAttribute(root, L"XDMCPHost", xdmcp_host); + getAttributeBool(root, L"XDMCPBroadcast", broadcast); + getAttributeBool(root, L"XDMCPIndirect", indirect); + + + + doc->Release(); +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..29f9352 --- /dev/null +++ b/config.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#include <string> +struct CConfig +{ + enum {MultiWindow, Fullscreen, Windowed, Nodecoration} window; + enum {NoClient, StartProgram, XDMCP} client; + bool local; + std::string display; + std::string protocol; + std::string program; + std::string host; + std::string user; + bool broadcast; + bool indirect; + std::string xdmcp_host; +#ifdef _DEBUG + CConfig() : window(MultiWindow), client(StartProgram), local(false), display("1"), + protocol("Putty"), program("xterm"), host("lupus"), user("ago"), + broadcast(false), indirect(false), xdmcp_host("lupus") {}; +#else + CConfig() : window(MultiWindow), client(StartProgram), local(false), display("0"), + protocol("Putty"), program("xterm"), host(""), user(""), + broadcast(true), indirect(false), xdmcp_host("") {}; +#endif + void Load(const char* filename); + void Save(const char* filename); +}; + +#endif @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#include "window/util.h" +#include "window/wizard.h" +#include "resources/resources.h" +#include "config.h" +#include <prsht.h> +#include <commctrl.h> + +#include <stdexcept> + +#include <X11/Xlib.h> + +/// @brief Send WM_ENDSESSION to all program windows. +/// This will shutdown the started xserver +BOOL CALLBACK KillWindowsProc(HWND hwnd, LPARAM lParam) +{ + SendMessage(hwnd, WM_ENDSESSION, 0, 0); + return TRUE; +} + +/// @brief Actual wizard implementation. +/// This is based on generic CWizard but handles the special dialogs +class CMyWizard : public CWizard +{ + public: + private: + CConfig config; /// Storage for config options. + public: + /// @brief Constructor. + /// Set wizard pages. + CMyWizard() : CWizard() + { + AddPage(IDD_DISPLAY, IDS_DISPLAY_TITLE, IDS_DISPLAY_SUBTITLE); + AddPage(IDD_CLIENTS, IDS_CLIENTS_TITLE, IDS_CLIENTS_SUBTITLE); + AddPage(IDD_PROGRAM, IDS_PROGRAM_TITLE, IDS_PROGRAM_SUBTITLE); + AddPage(IDD_XDMCP, IDS_XDMCP_TITLE, IDS_XDMCP_SUBTITLE); + //AddPage(IDD_FONTPATH, IDS_FONTPATH_TITLE, IDS_FONTPATH_SUBTITLE); + AddPage(IDD_FINISH, IDS_FINISH_TITLE, IDS_FINISH_SUBTITLE); + } + + virtual void LoadConfig(const char *filename) + { + try { + config.Load(filename); + } catch (std::runtime_error &e) + { + printf("Fehler: %s\n", e.what()); + } + } + + /// @brief Handle the PSN_WIZNEXT message. + /// @param hwndDlg Handle to active page dialog. + /// @param index Index of current page. + /// @return TRUE if the message was handled. FALSE otherwise. + virtual BOOL WizardNext(HWND hwndDlg, unsigned index) + { +#ifdef _DEBUG + printf("%s %d\n", __FUNCTION__, index); +#endif + switch (PageID(index)) + { + case IDD_DISPLAY: + // Check for select window mode + if (IsDlgButtonChecked(hwndDlg, IDC_MULTIWINDOW)) + config.window = CConfig::MultiWindow; + else if (IsDlgButtonChecked(hwndDlg, IDC_FULLSCREEN)) + config.window = CConfig::Fullscreen; + else if (IsDlgButtonChecked(hwndDlg, IDC_WINDOWED)) + config.window = CConfig::Windowed; + else if (IsDlgButtonChecked(hwndDlg, IDC_NODECORATION)) + config.window = CConfig::Nodecoration; + else + { + SetWindowLong(hwndDlg, DWL_MSGRESULT, -1); + return TRUE; + } + // Get selected display number + { + char buffer[512]; + GetDlgItemText(hwndDlg, IDC_DISPLAY, buffer, 512); + buffer[511] = 0; + config.display = buffer; + } + // Check for valid input + if (config.display.empty()) + SetWindowLong(hwndDlg, DWL_MSGRESULT, -1); + else + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIENTS); + return TRUE; + case IDD_CLIENTS: + // Check for select client startup method + if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT)) + { + config.client = CConfig::StartProgram; + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_PROGRAM); + } else if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP)) + { + config.client = CConfig::XDMCP; + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_XDMCP); + } else if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT_NONE)) + { + config.client = CConfig::NoClient; + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_FINISH); + } else + SetWindowLong(hwndDlg, DWL_MSGRESULT, -1); + return TRUE; + case IDD_PROGRAM: + // Check wether local or remote client should be started + if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT_LOCAL)) + config.local = true; + else if (IsDlgButtonChecked(hwndDlg, IDC_CLIENT_REMOTE)) + config.local = false; + else + { + SetWindowLong(hwndDlg, DWL_MSGRESULT, -1); + return TRUE; + } + // Read program, user and host name + { + char buffer[512]; + GetDlgItemText(hwndDlg, IDC_CLIENT_USER, buffer, 512); + buffer[511] = 0; + config.user = buffer; + GetDlgItemText(hwndDlg, IDC_CLIENT_HOST, buffer, 512); + buffer[511] = 0; + config.host = buffer; + GetDlgItemText(hwndDlg, IDC_CLIENT_PROGRAM, buffer, 512); + buffer[511] = 0; + config.program = buffer; + } + // Check for valid input + if (!config.local && (config.host.empty() || config.program.empty())) + SetWindowLong(hwndDlg, DWL_MSGRESULT, -1); + else + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_FINISH); + return TRUE; + case IDD_XDMCP: + // Check for broadcast + if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP_BROADCAST)) + config.broadcast = true; + else if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP_QUERY)) + config.broadcast = false; + else + { + SetWindowLong(hwndDlg, DWL_MSGRESULT, -1); + return TRUE; + } + // Check for indirect mode + if (IsDlgButtonChecked(hwndDlg, IDC_XDMCP_INDIRECT)) + config.indirect = true; + else + config.indirect = false; + // Read hostname + { + char buffer[512]; + GetDlgItemText(hwndDlg, IDC_XDMCP_HOST, buffer, 512); + buffer[511] = 0; + config.xdmcp_host = buffer; + } + // Check for valid input + if (!config.broadcast && config.xdmcp_host.empty()) + SetWindowLong(hwndDlg, DWL_MSGRESULT, -1); + else + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_FINISH); + return TRUE; + default: + break; + } + return FALSE; + } + /// @brief Handle PSN_WIZFINISH message. + /// @param hwndDlg Handle to active page dialog. + /// @param index Index of current page. + /// @return TRUE if the message was handled. FALSE otherwise. + virtual BOOL WizardFinish(HWND hwndDlg, unsigned index) + { +#ifdef _DEBUG + printf("finish %d\n", index); +#endif + return FALSE; + } + /// @brief Handle PSN_WIZBACK message. + /// Basicly handles switching to proper page (skipping XDMCP or program page + /// if required). + /// @param hwndDlg Handle to active page dialog. + /// @param index Index of current page. + /// @return TRUE if the message was handled. FALSE otherwise. + virtual BOOL WizardBack(HWND hwndDlg, unsigned index) + { + switch (PageID(index)) + { + case IDD_PROGRAM: + case IDD_XDMCP: + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIENTS); + return TRUE; + case IDD_FONTPATH: + case IDD_FINISH: // temporary. fontpath is disabled + switch (config.client) + { + case CConfig::NoClient: + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_CLIENTS); + return TRUE; + case CConfig::StartProgram: + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_PROGRAM); + return TRUE; + case CConfig::XDMCP: + SetWindowLong(hwndDlg, DWL_MSGRESULT, IDD_XDMCP); + return TRUE; + } + break; + } + return FALSE; + } + /// @brief Handle PSN_SETACTIVE message. + /// @param hwndDlg Handle to active page dialog. + /// @param index Index of current page. + /// @return TRUE if the message was handled. FALSE otherwise. + virtual BOOL WizardActivate(HWND hwndDlg, unsigned index) + { +#ifdef _DEBUG + printf("%s %d\n", __FUNCTION__, index); +#endif + switch (PageID(index)) + { + case IDD_CLIENTS: + // Enable or disable XDMCP radiobutton and text + EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP), config.window != CConfig::MultiWindow); + EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP_DESC), config.window != CConfig::MultiWindow); + break; + } + return FALSE; + } + protected: + /// @brief Enable or disable the control for remote clients. + /// @param hwndDlg Handle to active page dialog. + /// @param state State of control group. + void EnableRemoteProgramGroup(HWND hwndDlg, BOOL state) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_PROTOCOL), state); + EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_HOST), state); + EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_USER), state); + EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_PROTOCOL_DESC), state); + EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_HOST_DESC), state); + EnableWindow(GetDlgItem(hwndDlg, IDC_CLIENT_USER_DESC), state); + } + /// @brief Enable or disable the control for XDMCP connection. + /// @param hwndDlg Handle to active page dialog. + /// @param state State of control group. + void EnableXDMCPQueryGroup(HWND hwndDlg, BOOL state) + { + EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP_HOST), state); + EnableWindow(GetDlgItem(hwndDlg, IDC_XDMCP_INDIRECT), state); + } + /// @brief Fill program box with default values. + /// @param hwndDlg Handle to active page dialog. + void FillProgramBox(HWND hwndDlg) + { + HWND cbwnd = GetDlgItem(hwndDlg, IDC_CLIENT_PROGRAM); + if (cbwnd == NULL) + return; + SendMessage(cbwnd, CB_RESETCONTENT, 0, 0); + SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "xterm"); + SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "startkde"); + SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "gnome-session"); + SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) ".xinitrc"); + SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "wmaker"); + SendMessage(cbwnd, CB_SETCURSEL, 0, 0); + } + /// @brief Fill protocol box with default values. + /// @param hwndDlg Handle to active page dialog. + void FillProtocolBox(HWND hwndDlg) + { + HWND cbwnd = GetDlgItem(hwndDlg, IDC_CLIENT_PROTOCOL); + if (cbwnd == NULL) + return; + SendMessage(cbwnd, CB_RESETCONTENT, 0, 0); + SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "Putty"); + //SendMessage(cbwnd, CB_ADDSTRING, 0, (LPARAM) "OpenSSH"); + SendMessage(cbwnd, CB_SETCURSEL, 0, 0); + } + void ShowSaveDialog(HWND parent) + { + char szTitle[512]; + char szFilter[512]; + char szFileTitle[512]; + char szFile[MAX_PATH]; + HINSTANCE hInst = GetModuleHandle(NULL); + + LoadString(hInst, IDS_SAVE_TITLE, szTitle, sizeof(szTitle)); + LoadString(hInst, IDS_SAVE_FILETITLE, szFileTitle, sizeof(szFileTitle)); + LoadString(hInst, IDS_SAVE_FILTER, szFilter, sizeof(szFilter)); + for (unsigned i=0; szFilter[i]; i++) + if (szFilter[i] == '%') + szFilter[i] = '\0'; + + strcpy(szFile, "config.xlaunch"); + + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = parent; + ofn.lpstrFilter = szFilter; + ofn.lpstrFile= szFile; + ofn.nMaxFile = sizeof(szFile)/ sizeof(*szFile); + ofn.lpstrFileTitle = szFileTitle; + ofn.nMaxFileTitle = sizeof(szFileTitle); + ofn.lpstrInitialDir = (LPSTR)NULL; + ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT; + ofn.lpstrTitle = szTitle; + + if (GetSaveFileName(&ofn)) + { + try { + config.Save(ofn.lpstrFile); + } catch (std::runtime_error &e) + { + printf("Fehler: %s\n", e.what()); + } + } + } + public: + + /// @brief Handle messages fo the dialog pages. + /// @param hwndDlg Handle of active dialog. + /// @param uMsg Message code. + /// @param wParam Message parameter. + /// @param lParam Message parameter. + /// @param psp Handle to sheet paramters. + virtual INT_PTR PageDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, PROPSHEETPAGE *psp) + { + HWND hwnd; + switch (uMsg) + { + case WM_INITDIALOG: + switch (PageID(PageIndex(psp))) + { + case IDD_DISPLAY: + // Init display dialog. Enable correct check buttons + switch (config.window) + { + default: + case CConfig::MultiWindow: + CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_MULTIWINDOW); + break; + case CConfig::Fullscreen: + CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_FULLSCREEN); + break; + case CConfig::Windowed: + CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_WINDOWED); + break; + case CConfig::Nodecoration: + CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, IDC_NODECORATION); + break; + } + // Set display number + SetDlgItemText(hwndDlg, IDC_DISPLAY, config.display.c_str()); + break; + case IDD_CLIENTS: + // Init client dialog. Enable correct check buttons + switch (config.client) + { + default: + case CConfig::NoClient: + CheckRadioButton(hwndDlg, IDC_CLIENT_NONE, IDC_CLIENT, IDC_CLIENT_NONE); + break; + case CConfig::StartProgram: + CheckRadioButton(hwndDlg, IDC_CLIENT_NONE, IDC_CLIENT, IDC_CLIENT); + break; + case CConfig::XDMCP: + CheckRadioButton(hwndDlg, IDC_CLIENT_NONE, IDC_CLIENT, IDC_XDMCP); + break; + } + break; + case IDD_PROGRAM: + // Init program dialog. Check local and remote buttons + CheckRadioButton(hwndDlg, IDC_CLIENT_LOCAL, IDC_CLIENT_REMOTE, config.local?IDC_CLIENT_LOCAL:IDC_CLIENT_REMOTE); + EnableRemoteProgramGroup(hwndDlg, config.local?FALSE:TRUE); + // Fill combo boxes + FillProgramBox(hwndDlg); + FillProtocolBox(hwndDlg); + // Set edit fields + if (!config.program.empty()) + SetDlgItemText(hwndDlg, IDC_CLIENT_PROGRAM, config.program.c_str()); + SetDlgItemText(hwndDlg, IDC_CLIENT_USER, config.user.c_str()); + SetDlgItemText(hwndDlg, IDC_CLIENT_HOST, config.host.c_str()); + break; + case IDD_XDMCP: + // Init XDMCP dialog. Check broadcast and indirect button + CheckRadioButton(hwndDlg, IDC_XDMCP_QUERY, IDC_XDMCP_BROADCAST, config.broadcast?IDC_XDMCP_BROADCAST:IDC_XDMCP_QUERY); + CheckDlgButton(hwndDlg, IDC_XDMCP_INDIRECT, config.indirect?BST_CHECKED:BST_UNCHECKED); + EnableXDMCPQueryGroup(hwndDlg, config.broadcast?FALSE:TRUE); + // Set hostname + SetDlgItemText(hwndDlg, IDC_XDMCP_HOST, config.xdmcp_host.c_str()); + break; + + } + case WM_COMMAND: + // Handle control messages + switch (LOWORD(wParam)) + { + // Handle clicks on images. Check proper radiobutton + case IDC_MULTIWINDOW_IMG: + case IDC_FULLSCREEN_IMG: + case IDC_WINDOWED_IMG: + case IDC_NODECORATION_IMG: + CheckRadioButton(hwndDlg, IDC_MULTIWINDOW, IDC_NODECORATION, LOWORD(wParam)-4); + SetFocus(GetDlgItem(hwndDlg, LOWORD(wParam)-4)); + break; + // Disable unavailable controls + case IDC_CLIENT_REMOTE: + case IDC_CLIENT_LOCAL: + EnableRemoteProgramGroup(hwndDlg, LOWORD(wParam) == IDC_CLIENT_REMOTE); + break; + case IDC_XDMCP_QUERY: + case IDC_XDMCP_BROADCAST: + EnableXDMCPQueryGroup(hwndDlg, LOWORD(wParam) == IDC_XDMCP_QUERY); + break; + case IDC_FINISH_SAVE: + ShowSaveDialog(hwndDlg); + break; + } + } + // pass messages to parent + return CWizard::PageDispatch(hwndDlg, uMsg, wParam, lParam, psp); + } + + /// @brief Try to connect to server. + /// Repeat until successful, server died or maximum number of retries + /// reached. + Display *WaitForServer(HANDLE serverProcess) + { + int ncycles = 120; /* # of cycles to wait */ + int cycles; /* Wait cycle count */ + Display *xd; + + for (cycles = 0; cycles < ncycles; cycles++) { + if ((xd = XOpenDisplay(NULL))) { + return xd; + } + else { + if (WaitForSingleObject(serverProcess, 1000) == WAIT_TIMEOUT) + continue; + } + } + return NULL; + } + + /// @brief Do the actual start of Xming and clients + void StartUp() + { + std::string buffer; + std::string client; + + // Construct display strings + std::string display_id = ":" + config.display; + std::string display = "localhost" + display_id + ":0"; + +#ifdef _DEBUG + // Debug only: Switch to Xming installation directory + SetCurrentDirectory("C:\\Programme\\Xming"); +#endif + + // Build Xming commandline + buffer = "Xming " + display_id + " "; + switch (config.window) + { + case CConfig::MultiWindow: + buffer += "-multiwindow "; + break; + case CConfig::Fullscreen: + buffer += "-fullscreen "; + break; + case CConfig::Nodecoration: + buffer += "-nodecoration "; + break; + default: + break; + } + // Add XDMCP parameter + if (config.client == CConfig::XDMCP) + { + if (config.broadcast) + buffer += "-broadcast "; + else + { + if (config.indirect) + buffer += "-indirect "; + else + buffer += "-query "; + buffer += config.xdmcp_host; + } + } + + // Construct client commandline + if (config.client == CConfig::StartProgram) + { + if (!config.local) + { + char cmdline[512]; + std::string host = config.host; + if (!config.user.empty()) + host = config.user + "@" + config.host; + if (config.protocol == "Putty") + snprintf(cmdline,512,"plink -X %s %s", + host.c_str(),config.program.c_str()); + else + snprintf(cmdline,512,"ssh -Y %s %s", + host.c_str(),config.program.c_str()); + client += cmdline; + } else + client += config.program.c_str(); + } + + // Prepare program startup + STARTUPINFO si, sic; + PROCESS_INFORMATION pi, pic; + HANDLE handles[2]; + DWORD hcount = 0; + Display *dpy = NULL; + + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + ZeroMemory( &pi, sizeof(pi) ); + ZeroMemory( &sic, sizeof(sic) ); + sic.cb = sizeof(sic); + ZeroMemory( &pic, sizeof(pic) ); + + // Start Xming process. +#ifdef _DEBUG + printf("%s\n", buffer.c_str()); +#endif + if( !CreateProcess( NULL, (CHAR*)buffer.c_str(), NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi )) + throw win32_error("CreateProcess failed"); + handles[hcount++] = pi.hProcess; + + if (!client.empty()) + { + // Set DISPLAY variable + SetEnvironmentVariable("DISPLAY",display.c_str()); + + // Wait for server to startup + dpy = WaitForServer(pi.hProcess); + if (dpy == NULL) + { + while (hcount--) + TerminateProcess(handles[hcount], (DWORD)-1); + throw std::runtime_error("Connection to server failed"); + } + +#ifdef _DEBUG + printf("%s\n", client.c_str()); +#endif + + // Hide a console window + // FIXME: This may make it impossible to enter the password + sic.dwFlags = STARTF_USESHOWWINDOW; + sic.wShowWindow = SW_HIDE; + + // Start the child process. + if( !CreateProcess( NULL, (CHAR*)client.c_str(), NULL, NULL, + FALSE, 0, NULL, NULL, &sic, &pic )) + { + DWORD err = GetLastError(); + while (hcount--) + TerminateProcess(handles[hcount], (DWORD)-1); + throw win32_error("CreateProcess failed", err); + } + handles[hcount++] = pic.hProcess; + } + + // Wait until any child process exits. + DWORD ret = WaitForMultipleObjects(hcount, handles, FALSE, INFINITE ); + +#ifdef _DEBUG + printf("killing process!\n"); +#endif + // Check if Xming is still running + DWORD exitcode; + GetExitCodeProcess(pi.hProcess, &exitcode); + unsigned counter = 0; + while (exitcode == STILL_ACTIVE) + { + if (++counter > 10) + TerminateProcess(pi.hProcess, (DWORD)-1); + else + // Shutdown Xming (the soft way!) + EnumThreadWindows(pi.dwThreadId, KillWindowsProc, 0); + Sleep(500); + GetExitCodeProcess(pi.hProcess, &exitcode); + } + // Kill the client + TerminateProcess(pic.hProcess, (DWORD)-1); + + // Close process and thread handles. + CloseHandle( pi.hProcess ); + CloseHandle( pi.hThread ); + CloseHandle( pic.hProcess ); + CloseHandle( pic.hThread ); + } +}; + +int main(int argc, char **argv) +{ + try { + InitCommonControls(); + CMyWizard dialog; + + bool skip_wizard = false; + + for (int i = 1; i < argc; i++) + { + if (argv[i] == NULL) + continue; + + std::string arg(argv[i]); + if (arg == "-load" && i + 1 < argc) + { + i++; + dialog.LoadConfig(argv[i]); + continue; + } + if (arg == "-run" && i + 1 < argc) + { + i++; + dialog.LoadConfig(argv[i]); + skip_wizard = true; + continue; + } + } + + int ret = 0; + if (skip_wizard || (ret =dialog.ShowModal()) != 0) + dialog.StartUp(); +#ifdef _DEBUG + printf("return %d\n", ret); +#endif + return 0; + } catch (std::runtime_error &e) + { + printf("Fehler: %s\n", e.what()); + return -1; + } +} diff --git a/resources/dialog.rc b/resources/dialog.rc new file mode 100755 index 0000000..381304c --- /dev/null +++ b/resources/dialog.rc @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#include <windows.h> +#include "resources.h" + +#ifndef STR_CAPTION_DISPLAY +#include "strings.rc" +#endif + +IDD_DISPLAY DIALOGEX 0, 0, 317, 143 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTERMOUSE +CAPTION STR_CAPTION_DISPLAY +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + AUTORADIOBUTTON STR_MULTIWINDOW,IDC_MULTIWINDOW,7,25,70,24,BS_MULTILINE|BS_TOP + AUTORADIOBUTTON STR_FULLSCREEN,IDC_FULLSCREEN,157,25,70,24,BS_MULTILINE|BS_TOP + AUTORADIOBUTTON STR_WINDOWED,IDC_WINDOWED,7,75,70,24,BS_MULTILINE|BS_TOP + AUTORADIOBUTTON STR_NODECORATION,IDC_NODECORATION,157,75,70,24,BS_MULTILINE|BS_TOP + + CONTROL "IMG_MULTIWINDOW",IDC_MULTIWINDOW_IMG,"Static",SS_BITMAP | SS_NOTIFY,80,10,0,0 + CONTROL "IMG_FULLSCREEN",IDC_FULLSCREEN_IMG,"Static",SS_BITMAP | SS_NOTIFY,230,10,0,0 + CONTROL "IMG_WINDOWED",IDC_WINDOWED_IMG,"Static",SS_BITMAP | SS_NOTIFY,80,60,0,0 + CONTROL "IMG_NODECORATION",IDC_NODECORATION_IMG,"Static",SS_BITMAP | SS_NOTIFY,230,60,0,0 + + LTEXT STR_DISPLAY_DESC,IDC_DISPLAY_DESC,7,120,64,12 + EDITTEXT IDC_DISPLAY,80,118,67,12,ES_NUMBER +END + +IDD_CLIENTS DIALOGEX 0, 0, 317, 143 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTERMOUSE +CAPTION STR_CAPTION_CLIENTS +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + AUTORADIOBUTTON STR_CLIENT_NONE,IDC_CLIENT_NONE,7,14,300,10 + AUTORADIOBUTTON STR_CLIENT,IDC_CLIENT,7,56,300,10 + AUTORADIOBUTTON STR_XDMCP,IDC_XDMCP,7,98,300,10 + + LTEXT STR_CLIENT_NONE_DESC,IDC_CLIENT_NONE_DESC,19,28,280,27 + LTEXT STR_CLIENT_DESC,IDC_CLIENT_DESC,19,70,280,27 + LTEXT STR_XDMCP_DESC,IDC_XDMCP_DESC,19,112,280,27 +END + +IDD_PROGRAM DIALOGEX 0, 0, 317, 143 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTERMOUSE +CAPTION STR_CAPTION_PROGRAM +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT STR_CLIENT_PROGRAM_DESC,IDC_CLIENT_PROGRAM_DESC,7,14,64,10 + COMBOBOX IDC_CLIENT_PROGRAM,70,12,64,54,CBS_DROPDOWN | WS_VSCROLL + + AUTORADIOBUTTON STR_CLIENT_LOCAL,IDC_CLIENT_LOCAL,7,28,300,10 + AUTORADIOBUTTON STR_CLIENT_REMOTE,IDC_CLIENT_REMOTE,7,42,300,10 + + LTEXT STR_CLIENT_PROTOCOL_DESC,IDC_CLIENT_PROTOCOL_DESC,19,56,70,10 + COMBOBOX IDC_CLIENT_PROTOCOL,100,54,64,54,CBS_DROPDOWNLIST | WS_VSCROLL + + LTEXT STR_CLIENT_HOST_DESC,IDC_CLIENT_HOST_DESC,19,70,70,10 + LTEXT STR_CLIENT_USER_DESC,IDC_CLIENT_USER_DESC,19,84,70,10 + EDITTEXT IDC_CLIENT_HOST,100,68,64,12 + EDITTEXT IDC_CLIENT_USER,100,82,64,12 +END + +IDD_XDMCP DIALOGEX 0, 0, 317, 143 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTERMOUSE +CAPTION STR_CAPTION_XDMCP +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + AUTORADIOBUTTON STR_XDMCP_QUERY, IDC_XDMCP_QUERY,7,14,64,10 + EDITTEXT IDC_XDMCP_HOST,78,12,64,12 + AUTOCHECKBOX STR_XDMCP_INDIRECT,IDC_XDMCP_INDIRECT,19,28,280,10 + AUTORADIOBUTTON STR_XDMCP_BROADCAST, IDC_XDMCP_BROADCAST,7,42,300,10 + LTEXT STR_XDMCP_QUERY_DESC,IDC_XDMCP_QUERY_DESC,7,56,300,42 +END + +IDD_FONTPATH DIALOGEX 0, 0, 317, 143 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTERMOUSE +CAPTION STR_CAPTION_FONTPATH +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN +END + +IDD_FINISH DIALOGEX 0, 0, 317, 143 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTERMOUSE +CAPTION STR_CAPTION_FINISH +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + LTEXT STR_FINISH_DESC,IDC_FINISH_DESC,7,14,300,28 + LTEXT STR_FINISH_SAVE_DESC,IDC_FINISH_SAVE_DESC,7,56,300,12 + PUSHBUTTON STR_FINISH_SAVE,IDC_FINISH_SAVE,7,68,75,14 +END diff --git a/resources/fullscreen.bmp b/resources/fullscreen.bmp Binary files differnew file mode 100755 index 0000000..0d051f0 --- /dev/null +++ b/resources/fullscreen.bmp diff --git a/resources/images.rc b/resources/images.rc new file mode 100755 index 0000000..07d5f1f --- /dev/null +++ b/resources/images.rc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +IMG_MULTIWINDOW BITMAP "resources\\multiwindow.bmp" +IMG_WINDOWED BITMAP "resources\\windowed.bmp" +IMG_FULLSCREEN BITMAP "resources\\fullscreen.bmp" +IMG_NODECORATION BITMAP "resources\\nodecoration.bmp" diff --git a/resources/multiwindow.bmp b/resources/multiwindow.bmp Binary files differnew file mode 100755 index 0000000..0755c87 --- /dev/null +++ b/resources/multiwindow.bmp diff --git a/resources/nodecoration.bmp b/resources/nodecoration.bmp Binary files differnew file mode 100755 index 0000000..e9e1ce6 --- /dev/null +++ b/resources/nodecoration.bmp diff --git a/resources/resources.h b/resources/resources.h new file mode 100755 index 0000000..f268052 --- /dev/null +++ b/resources/resources.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#define IDC_STATIC -1 + +#define IDD_WELCOME 100 +#define IDD_FINISH 101 +#define IDD_DISPLAY 102 +#define IDD_CLIENTS 103 +#define IDD_PROGRAM 104 +#define IDD_XDMCP 105 +#define IDD_FONTPATH 106 + +#define IDS_DISPLAY_TITLE 300 +#define IDS_DISPLAY_SUBTITLE 301 +#define IDS_CLIENTS_TITLE 302 +#define IDS_CLIENTS_SUBTITLE 303 +#define IDS_PROGRAM_TITLE 304 +#define IDS_PROGRAM_SUBTITLE 305 +#define IDS_XDMCP_TITLE 306 +#define IDS_XDMCP_SUBTITLE 307 +#define IDS_FONTPATH_TITLE 308 +#define IDS_FONTPATH_SUBTITLE 309 +#define IDS_FINISH_TITLE 310 +#define IDS_FINISH_SUBTITLE 311 +#define IDS_SAVE_TITLE 320 +#define IDS_SAVE_FILETITLE 321 +#define IDS_SAVE_FILTER 322 + +#define IDC_MULTIWINDOW 200 +#define IDC_WINDOWED 201 +#define IDC_FULLSCREEN 202 +#define IDC_NODECORATION 203 +#define IDC_MULTIWINDOW_IMG 204 +#define IDC_WINDOWED_IMG 205 +#define IDC_FULLSCREEN_IMG 206 +#define IDC_NODECORATION_IMG 207 +#define IDC_DISPLAY 208 +#define IDC_DISPLAY_DESC 209 + +#define IDC_CLIENT_NONE 210 +#define IDC_XDMCP 211 +#define IDC_CLIENT 212 +#define IDC_CLIENT_LOCAL 213 +#define IDC_CLIENT_REMOTE 214 +#define IDC_CLIENT_HOST 215 +#define IDC_CLIENT_USER 216 +#define IDC_CLIENT_PROTOCOL 217 +#define IDC_CLIENT_CONFIGURE 218 +#define IDC_CLIENT_PROGRAM 219 +#define IDC_XDMCP_QUERY 220 +#define IDC_XDMCP_BROADCAST 221 +#define IDC_XDMCP_INDIRECT 222 +#define IDC_XDMCP_HOST 223 +#define IDC_CLIENT_NONE_DESC 224 +#define IDC_XDMCP_DESC 225 +#define IDC_CLIENT_DESC 226 +#define IDC_XDMCP_QUERY_DESC 227 +#define IDC_CLIENT_PROGRAM_DESC 228 +#define IDC_CLIENT_HOST_DESC 229 +#define IDC_CLIENT_USER_DESC 230 +#define IDC_CLIENT_PROTOCOL_DESC 231 + +#define IDC_FONTPATH_DESC 240 + +#define IDC_FINISH_DESC 250 +#define IDC_FINISH_SAVE 251 +#define IDC_FINISH_SAVE_DESC 252 diff --git a/resources/resources.rc b/resources/resources.rc new file mode 100755 index 0000000..07fd52f --- /dev/null +++ b/resources/resources.rc @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#include <windows.h> + +#include "resources.h" +#include "images.rc" +#include "dialog.rc" diff --git a/resources/strings.rc b/resources/strings.rc new file mode 100644 index 0000000..238511d --- /dev/null +++ b/resources/strings.rc @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#define STR_CAPTION_DISPLAY "Display settings" +#define STR_MULTIWINDOW "Multiple windows" +#define STR_FULLSCREEN "Fullscreen" +#define STR_WINDOWED "One large window" +#define STR_NODECORATION "One window without titlebar" +#define STR_DISPLAY_DESC "Display number" + +#define STR_CAPTION_CLIENTS "Client startup" +#define STR_CLIENT_NONE "Start no client" +#define STR_CLIENT_NONE_DESC "This will just start the xserver. You will be able to start local clients later." +#define STR_CLIENT "Start a program" +#define STR_CLIENT_DESC "This will start a local or remote program which will connect to the xserver. You will be able to start local clients later too. Remote programs are started using SSH." +#define STR_XDMCP "Open session via XDMCP" +#define STR_XDMCP_DESC "This will start a remote XDMCP session. Starting local clients later is limited. This option is not available with the ""Multiple windows"" mode." + +#define STR_CAPTION_PROGRAM "Start program" +#define STR_CLIENT_PROGRAM_DESC "Start program" +#define STR_CLIENT_LOCAL "Start program on this computer" +#define STR_CLIENT_REMOTE "Start program on remote computer" +#define STR_CLIENT_PROTOCOL_DESC "Connect using" +#define STR_CLIENT_HOST_DESC "Connect to computer" +#define STR_CLIENT_USER_DESC "Login as user" + + +#define STR_CAPTION_XDMCP "XDMCP settings" +#define STR_XDMCP_QUERY "Connect to host" +#define STR_XDMCP_INDIRECT "Use indirect connect" +#define STR_XDMCP_BROADCAST "Search for hosts (broadcast)" +#define STR_XDMCP_QUERY_DESC "Some XDMCP servers must be configured to allow remote connections. Please check the documentation about configuring XDMCP servers." + + +#define STR_CAPTION_FONTPATH "Fontpath settings" + +#define STR_CAPTION_FINISH "Finish configuration" +#define STR_FINISH_DESC "Configuration is complete. Clish Finish to start Xming." +#define STR_FINISH_SAVE_DESC "You may also save the configuration for later use." +#define STR_FINISH_SAVE "Save configuration" + +#define STR_DISPLAY_TITLE "Select display settings" +#define STR_DISPLAY_SUBTITLE "Choose how Xming display programs" +#define STR_CLIENTS_TITLE "Select how to start clients" +#define STR_CLIENTS_SUBTITLE "" +#define STR_PROGRAM_TITLE "Specify the program to start" +#define STR_PROGRAM_SUBTITLE "" +#define STR_XDMCP_TITLE "Configure a remote XDMCP connection" +#define STR_XDMCP_SUBTITLE "" +#define STR_FONTPATH_TITLE "Define font locations" +#define STR_FONTPATH_SUBTITLE "" +#define STR_FINISH_TITLE "Configuration complete" +#define STR_FINISH_SUBTITLE "" + +#define STR_SAVE_TITLE "Save configuration" +#define STR_SAVE_FILETITLE "Filename" +#define STR_SAVE_FILTER "Xlaunch Files (*.xlaunch)%*.xlaunch%%" + +STRINGTABLE +BEGIN + IDS_DISPLAY_TITLE STR_DISPLAY_TITLE + IDS_DISPLAY_SUBTITLE STR_DISPLAY_SUBTITLE + IDS_CLIENTS_TITLE STR_CLIENTS_TITLE + IDS_CLIENTS_SUBTITLE STR_CLIENTS_SUBTITLE + IDS_PROGRAM_TITLE STR_PROGRAM_TITLE + IDS_PROGRAM_SUBTITLE STR_PROGRAM_SUBTITLE + IDS_XDMCP_TITLE STR_XDMCP_TITLE + IDS_XDMCP_SUBTITLE STR_XDMCP_SUBTITLE + IDS_FONTPATH_TITLE STR_FONTPATH_TITLE + IDS_FONTPATH_SUBTITLE STR_FONTPATH_SUBTITLE + IDS_FINISH_TITLE STR_FINISH_TITLE + IDS_FINISH_SUBTITLE STR_FINISH_SUBTITLE + IDS_SAVE_TITLE STR_SAVE_TITLE + IDS_SAVE_FILETITLE STR_SAVE_FILETITLE + IDS_SAVE_FILTER STR_SAVE_FILTER +END diff --git a/resources/windowed.bmp b/resources/windowed.bmp Binary files differnew file mode 100755 index 0000000..9eff2bf --- /dev/null +++ b/resources/windowed.bmp diff --git a/window/dialog.cc b/window/dialog.cc new file mode 100755 index 0000000..f5a9758 --- /dev/null +++ b/window/dialog.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#include <stdio.h> +#include "dialog.h" +#include "util.h" + +CBaseDialog::CBaseDialog() : CWindow(""), result(0) +{ +} + +CDialog::CDialog(const char *res) : CBaseDialog(), resourcename(res) +{ +} + +HWND CDialog::CreateWindowHandle() +{ + HWND ret = CreateDialog( + GetModuleHandle(NULL), + resourcename.c_str(), + NULL, + DialogProc); + if (ret == NULL) + throw win32_error("CreateDialog failed"); + return ret; +} + +INT_PTR CALLBACK CBaseDialog::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MessageDebug::debug(hwndDlg, uMsg, wParam, lParam, __FUNCTION__); + CBaseDialog* dialog = (CDialog*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + if (dialog != NULL) + return dialog->DlgDispatch(hwndDlg, uMsg, wParam, lParam); + return FALSE; +} + +INT_PTR CBaseDialog::DlgDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + result = wParam; + EndDialog(hwndDlg, wParam); + DestroyWindow(hwndDlg); + return TRUE; + } + break; + } + return FALSE; +} + +INT_PTR CDialog::DlgDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return CBaseDialog::DlgDispatch(hwndDlg, uMsg, wParam, lParam); +} + +int CBaseDialog::Execute() +{ + return CWindow::ShowModal(); +} diff --git a/window/dialog.h b/window/dialog.h new file mode 100755 index 0000000..073394b --- /dev/null +++ b/window/dialog.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#ifndef __DIALOG_H__ +#define __DIALOG_H__ + +#include "window.h" +class CBaseDialog : public CWindow +{ + private: + int result; + protected: + static INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual INT_PTR DlgDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + public: + CBaseDialog(); + int Execute(); +}; + +class CDialog : public CBaseDialog +{ + private: + std::string resourcename; + protected: + virtual INT_PTR DlgDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual HWND CreateWindowHandle(); + public: + CDialog(const char *res); +}; + + +#endif diff --git a/window/util.cc b/window/util.cc new file mode 100644 index 0000000..884690f --- /dev/null +++ b/window/util.cc @@ -0,0 +1,1111 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#include "util.h" + +std::string win32_error::message(DWORD errorcode) +{ + LPVOID lpMsgBuf; + if (!FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errorcode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL )) + { + return "Unknown error in FormatMessage"; + } + + std::string ret((LPCTSTR)lpMsgBuf); + LocalFree( lpMsgBuf ); + return ret; +} + +void MessageDebug::debug(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, const char *prefix) +{ +#ifdef _DEBUG + static const char *psn_notify[] = { + "PSN_SETACTIVE", + "PSN_KILLACTIVE", + "PSN_APPLY", + "PSN_RESET", + NULL, + "PSN_HELP", + "PSN_WIZBACK", + "PSN_WIZNEXT", + "PSN_WIZFINISH", + "PSN_QUERYCANCEL" }; + if (uMsg == WM_NOTIFY) + { + LPNMHDR pnmh = (LPNMHDR)lParam; + int psn_index = -(int)pnmh->code - 200; + if (psn_index >= 0 && psn_index < 10 && psn_notify[psn_index]) + printf("%s: %08x %04x WM_NOTIFY (%s)\n", prefix, hwnd, wParam, psn_notify[psn_index]); + else if (pnmh->code < NOTIFY_NAMES_LEN && notify_names[pnmh->code]) + printf("%s: %08x %04x WM_NOTIFY (%s)\n", prefix, hwnd, wParam, notify_names[pnmh->code]); + else + printf("%s: %08x %04x WM_NOTIFY (%u)\n", prefix, hwnd, wParam, pnmh->code); + } + else if (uMsg >= MESSAGE_NAMES_LEN) + if (uMsg >= WM_USER) + printf("%s: %08x %04x %08x WM_USER + %d\n", prefix, hwnd, wParam, lParam, uMsg - WM_USER); + else + printf("%s: %08x %04x %08x %d\n", prefix, hwnd, wParam, lParam, uMsg); + else if (uMsg >= 0 && uMsg < MESSAGE_NAMES_LEN && message_names[uMsg]) + printf("%s: %08x %04x %08x %s\n", prefix, hwnd, wParam, lParam, message_names[uMsg]); +#endif +} + + +const char * MessageDebug::message_names[MESSAGE_NAMES_LEN] = { + "WM_NULL", + "WM_CREATE", + "WM_DESTROY", + "WM_MOVE", + "4", + "WM_SIZE", + "WM_ACTIVATE", + "WM_SETFOCUS", + "WM_KILLFOCUS", + "9", + "WM_ENABLE", + "WM_SETREDRAW", + "WM_SETTEXT", + "WM_GETTEXT", + "WM_GETTEXTLENGTH", + "WM_PAINT", + "WM_CLOSE", + "WM_QUERYENDSESSION", + "WM_QUIT", + "WM_QUERYOPEN", + "WM_ERASEBKGND", + "WM_SYSCOLORCHANGE", + "WM_ENDSESSION", + "23", + "WM_SHOWWINDOW", + "25", + "WM_WININICHANGE", + "WM_DEVMODECHANGE", + "WM_ACTIVATEAPP", + "WM_FONTCHANGE", + "WM_TIMECHANGE", + "WM_CANCELMODE", + NULL /* WM_SETCURSOR */, + "WM_MOUSEACTIVATE", + "WM_CHILDACTIVATE", + "WM_QUEUESYNC", + "WM_GETMINMAXINFO", + "37", + "WM_PAINTICON", + "WM_ICONERASEBKGND", + "WM_NEXTDLGCTL", + "41", + "WM_SPOOLERSTATUS", + "WM_DRAWITEM", + "WM_MEASUREITEM", + "WM_DELETEITEM", + "WM_VKEYTOITEM", + "WM_CHARTOITEM", + "WM_SETFONT", + "WM_GETFONT", + "WM_SETHOTKEY", + "WM_GETHOTKEY", + "52", + "53", + "54", + "WM_QUERYDRAGICON", + "56", + "WM_COMPAREITEM", + "58", + "59", + "60", + "61", + "62", + "63", + "64", + "WM_COMPACTING", + "66", + "67", + "WM_COMMNOTIFY", + "69", + "WM_WINDOWPOSCHANGING", + "WM_WINDOWPOSCHANGED", + "WM_POWER", + "73", + "WM_COPYDATA", + "WM_CANCELJOURNAL", + "76", + "77", + "WM_NOTIFY", + "79", + "WM_INPUTLANGCHANGEREQUEST", + "WM_INPUTLANGCHANGE", + "WM_TCARD", + "WM_HELP", + "WM_USERCHANGED", + "WM_NOTIFYFORMAT", + "86", + "87", + "88", + "89", + "90", + "91", + "92", + "93", + "94", + "95", + "96", + "97", + "98", + "99", + "100", + "101", + "102", + "103", + "104", + "105", + "106", + "107", + "108", + "109", + "110", + "111", + "112", + "113", + "114", + "115", + "116", + "117", + "118", + "119", + "120", + "121", + "122", + "WM_CONTEXTMENU", + "WM_STYLECHANGING", + "WM_STYLECHANGED", + "WM_DISPLAYCHANGE", + "WM_GETICON", + "WM_SETICON", + "WM_NCCREATE", + "WM_NCDESTROY", + "WM_NCCALCSIZE", + NULL /* WM_NCHITTEST */, + "WM_NCPAINT", + "WM_NCACTIVATE", + "WM_GETDLGCODE", + "WM_SYNCPAINT", + "137", + "138", + "139", + "140", + "141", + "142", + "143", + "144", + "145", + "146", + "147", + "148", + "149", + "150", + "151", + "152", + "153", + "154", + "155", + "156", + "157", + "158", + "159", + NULL /* WM_NCMOUSEMOVE */, + "WM_NCLBUTTONDOWN", + "WM_NCLBUTTONUP", + "WM_NCLBUTTONDBLCLK", + "WM_NCRBUTTONDOWN", + "WM_NCRBUTTONUP", + "WM_NCRBUTTONDBLCLK", + "WM_NCMBUTTONDOWN", + "WM_NCMBUTTONUP", + "WM_NCMBUTTONDBLCLK", + "170", + "171", + "172", + "173", + "174", + "175", + "176", + "177", + "178", + "179", + "180", + "181", + "182", + "183", + "184", + "185", + "186", + "187", + "188", + "189", + "190", + "191", + "192", + "193", + "194", + "195", + "196", + "197", + "198", + "199", + "200", + "201", + "202", + "203", + "204", + "205", + "206", + "207", + "208", + "209", + "210", + "211", + "212", + "213", + "214", + "215", + "216", + "217", + "218", + "219", + "220", + "221", + "222", + "223", + "224", + "225", + "226", + "227", + "228", + "229", + "230", + "231", + "232", + "233", + "234", + "235", + "236", + "237", + "238", + "239", + "240", + "241", + "242", + "243", + "244", + "245", + "246", + "247", + "248", + "249", + "250", + "251", + "252", + "253", + "254", + "255", + "WM_KEYDOWN", + "WM_KEYUP", + "WM_CHAR", + "WM_DEADCHAR", + "WM_SYSKEYDOWN", + "WM_SYSKEYUP", + "WM_SYSCHAR", + "WM_SYSDEADCHAR", + "WM_CONVERTREQUESTEX", + "265", + "266", + "267", + "268", + "WM_IME_STARTCOMPOSITION", + "WM_IME_ENDCOMPOSITION", + "WM_IME_KEYLAST", + "WM_INITDIALOG", + "WM_COMMAND", + "WM_SYSCOMMAND", + NULL /* WM_TIMER */, + "WM_HSCROLL", + "WM_VSCROLL", + "WM_INITMENU", + "WM_INITMENUPOPUP", + "280", + "281", + "282", + "283", + "284", + "285", + "286", + "WM_MENUSELECT", + "WM_MENUCHAR", + "WM_ENTERIDLE", + "290", + "291", + "292", + "293", + "294", + "295", + "296", + "297", + "298", + "299", + "300", + "301", + "302", + "303", + "304", + "305", + "WM_CTLCOLORMSGBOX", + "WM_CTLCOLOREDIT", + "WM_CTLCOLORLISTBOX", + "WM_CTLCOLORBTN", + "WM_CTLCOLORDLG", + "WM_CTLCOLORSCROLLBAR", + "WM_CTLCOLORSTATIC", + "313", + "314", + "315", + "316", + "317", + "318", + "319", + "320", + "321", + "322", + "323", + "324", + "325", + "326", + "327", + "328", + "329", + "330", + "331", + "332", + "333", + "334", + "335", + "336", + "337", + "338", + "339", + "340", + "341", + "342", + "343", + "344", + "345", + "346", + "347", + "348", + "349", + "350", + "351", + "352", + "353", + "354", + "355", + "356", + "357", + "358", + "359", + "360", + "361", + "362", + "363", + "364", + "365", + "366", + "367", + "368", + "369", + "370", + "371", + "372", + "373", + "374", + "375", + "376", + "377", + "378", + "379", + "380", + "381", + "382", + "383", + "384", + "385", + "386", + "387", + "388", + "389", + "390", + "391", + "392", + "393", + "394", + "395", + "396", + "397", + "398", + "399", + "400", + "401", + "402", + "403", + "404", + "405", + "406", + "407", + "408", + "409", + "410", + "411", + "412", + "413", + "414", + "415", + "416", + "417", + "418", + "419", + "420", + "421", + "422", + "423", + "424", + "425", + "426", + "427", + "428", + "429", + "430", + "431", + "432", + "433", + "434", + "435", + "436", + "437", + "438", + "439", + "440", + "441", + "442", + "443", + "444", + "445", + "446", + "447", + "448", + "449", + "450", + "451", + "452", + "453", + "454", + "455", + "456", + "457", + "458", + "459", + "460", + "461", + "462", + "463", + "464", + "465", + "466", + "467", + "468", + "469", + "470", + "471", + "472", + "473", + "474", + "475", + "476", + "477", + "478", + "479", + "480", + "481", + "482", + "483", + "484", + "485", + "486", + "487", + "488", + "489", + "490", + "491", + "492", + "493", + "494", + "495", + "496", + "497", + "498", + "499", + "500", + "501", + "502", + "503", + "504", + "505", + "506", + "507", + "508", + "509", + "510", + "511", + NULL /* WM_MOUSEMOVE */, + "WM_LBUTTONDOWN", + "WM_LBUTTONUP", + "WM_LBUTTONDBLCLK", + "WM_RBUTTONDOWN", + "WM_RBUTTONUP", + "WM_RBUTTONDBLCLK", + "WM_MBUTTONDOWN", + "WM_MBUTTONUP", + "WM_MBUTTONDBLCLK", + "WM_MOUSEWHEEL", + "WM_XBUTTONDOWN", + "WM_XBUTTONUP", + "WM_XBUTTONDBLCLK", + "526", + "527", + "WM_PARENTNOTIFY", + "WM_ENTERMENULOOP", + "WM_EXITMENULOOP", + "WM_NEXTMENU", + "WM_SIZING", + "WM_CAPTURECHANGED", + "WM_MOVING", + "535", + "WM_POWERBROADCAST", + "WM_DEVICECHANGE", + "538", + "539", + "540", + "541", + "542", + "543", + "WM_MDICREATE", + "WM_MDIDESTROY", + "WM_MDIACTIVATE", + "WM_MDIRESTORE", + "WM_MDINEXT", + "WM_MDIMAXIMIZE", + "WM_MDITILE", + "WM_MDICASCADE", + "WM_MDIICONARRANGE", + "WM_MDIGETACTIVE", + "554", + "555", + "556", + "557", + "558", + "559", + "WM_MDISETMENU", + "WM_ENTERSIZEMOVE", + "WM_EXITSIZEMOVE", + "WM_DROPFILES", + "WM_MDIREFRESHMENU", + "565", + "566", + "567", + "568", + "569", + "570", + "571", + "572", + "573", + "574", + "575", + "576", + "577", + "578", + "579", + "580", + "581", + "582", + "583", + "584", + "585", + "586", + "587", + "588", + "589", + "590", + "591", + "592", + "593", + "594", + "595", + "596", + "597", + "598", + "599", + "600", + "601", + "602", + "603", + "604", + "605", + "606", + "607", + "608", + "609", + "610", + "611", + "612", + "613", + "614", + "615", + "616", + "617", + "618", + "619", + "620", + "621", + "622", + "623", + "624", + "625", + "626", + "627", + "628", + "629", + "630", + "631", + "632", + "633", + "634", + "635", + "636", + "637", + "638", + "639", + "640", + "WM_IME_SETCONTEXT", + "WM_IME_NOTIFY", + "WM_IME_CONTROL", + "WM_IME_COMPOSITIONFULL", + "WM_IME_SELECT", + "WM_IME_CHAR", + "647", + "648", + "649", + "650", + "651", + "652", + "653", + "654", + "655", + "WM_IME_KEYDOWN", + "WM_IME_KEYUP", + "658", + "659", + "660", + "661", + "662", + "663", + "664", + "665", + "666", + "667", + "668", + "669", + "670", + "671", + "672", + "WM_MOUSEHOVER", + "674", + "WM_MOUSELEAVE", + "676", + "677", + "678", + "679", + "680", + "681", + "682", + "683", + "684", + "685", + "686", + "687", + "688", + "689", + "690", + "691", + "692", + "693", + "694", + "695", + "696", + "697", + "698", + "699", + "700", + "701", + "702", + "703", + "704", + "705", + "706", + "707", + "708", + "709", + "710", + "711", + "712", + "713", + "714", + "715", + "716", + "717", + "718", + "719", + "720", + "721", + "722", + "723", + "724", + "725", + "726", + "727", + "728", + "729", + "730", + "731", + "732", + "733", + "734", + "735", + "736", + "737", + "738", + "739", + "740", + "741", + "742", + "743", + "744", + "745", + "746", + "747", + "748", + "749", + "750", + "751", + "752", + "753", + "754", + "755", + "756", + "757", + "758", + "759", + "760", + "761", + "762", + "763", + "764", + "765", + "766", + "767", + "WM_CUT", + "WM_COPY", + "WM_PASTE", + "WM_CLEAR", + "WM_UNDO", + "WM_RENDERFORMAT", + "WM_RENDERALLFORMATS", + "WM_DESTROYCLIPBOARD", + "WM_DRAWCLIPBOARD", + "WM_PAINTCLIPBOARD", + "WM_VSCROLLCLIPBOARD", + "WM_SIZECLIPBOARD", + "WM_ASKCBFORMATNAME", + "WM_CHANGECBCHAIN", + "WM_HSCROLLCLIPBOARD", + "WM_QUERYNEWPALETTE", + "WM_PALETTEISCHANGING", + "WM_PALETTECHANGED", + "WM_HOTKEY", + "787", + "788", + "789", + "790", + "WM_PRINT", + "WM_PRINTCLIENT", + "793", + "794", + "795", + "796", + "797", + "798", + "799", + "800", + "801", + "802", + "803", + "804", + "805", + "806", + "807", + "808", + "809", + "810", + "811", + "812", + "813", + "814", + "815", + "816", + "817", + "818", + "819", + "820", + "821", + "822", + "823", + "824", + "825", + "826", + "827", + "828", + "829", + "830", + "831", + "832", + "833", + "834", + "835", + "836", + "837", + "838", + "839", + "840", + "841", + "842", + "843", + "844", + "845", + "846", + "847", + "848", + "849", + "850", + "851", + "852", + "853", + "854", + "855", + "856", + "857", + "858", + "859", + "860", + "861", + "862", + "863", + "864", + "865", + "866", + "867", + "868", + "869", + "870", + "871", + "872", + "873", + "874", + "875", + "876", + "877", + "878", + "879", + "880", + "881", + "882", + "883", + "884", + "885", + "886", + "887", + "888", + "889", + "890", + "891", + "892", + "893", + "894", + "895", + "896", + "897", + "898", + "899", + "900", + "901", + "902", + "903", + "904", + "905", + "906", + "907", + "908", + "909", + "910", + "911", + "912", + "913", + "914", + "915", + "916", + "917", + "918", + "919", + "920", + "921", + "922", + "923", + "924", + "925", + "926", + "927", + "928", + "929", + "930", + "931", + "932", + "933", + "934", + "935", + "936", + "937", + "938", + "939", + "940", + "941", + "942", + "943", + "944", + "945", + "946", + "947", + "948", + "949", + "950", + "951", + "952", + "953", + "954", + "955", + "956", + "957", + "958", + "959", + "960", + "961", + "962", + "963", + "964", + "965", + "966", + "967", + "968", + "969", + "970", + "971", + "972", + "973", + "974", + "975", + "976", + "977", + "978", + "979", + "980", + "981", + "982", + "983", + "984", + "985", + "986", + "987", + "988", + "989", + "990", + "991", + "992", + "993", + "994", + "995", + "996", + "997", + "998", + "999", + "1000", + "1001", + "1002", + "1003", + "1004", + "1005", + "1006", + "1007", + "1008", + "1009", + "1010", + "1011", + "1012", + "1013", + "1014", + "1015", + "1016", + "1017", + "1018", + "1019", + "1020", + "1021", + "1022", + "1023" +}; diff --git a/window/util.h b/window/util.h new file mode 100644 index 0000000..cd21da6 --- /dev/null +++ b/window/util.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include <windows.h> +#include <stdexcept> + + +class win32_error : public std::runtime_error +{ + public: + static std::string message(DWORD code); + DWORD errorcode; + win32_error(const std::string &msg,DWORD code = GetLastError()) : std::runtime_error(msg + ":" + message(code)), errorcode(code) {}; +}; + +#define MESSAGE_NAMES_LEN 1024 +#define NOTIFY_NAMES_LEN 0 +class MessageDebug +{ + protected: + static const char * message_names[MESSAGE_NAMES_LEN]; + static const char * notify_names[NOTIFY_NAMES_LEN]; + public: + static void debug(HWND handle, UINT uMsg, WPARAM wParam, LPARAM lParam, const char *prefix); +}; + + +#endif diff --git a/window/window.cc b/window/window.cc new file mode 100755 index 0000000..6572b49 --- /dev/null +++ b/window/window.cc @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#include "window.h" +#include "util.h" +#include <stdio.h> +#include <stdexcept> + +CWindow::CWindowClass CWindow::windowClass("CWINDOWCLASS", DefWindowProc); + +CWindow::CWindowClass::CWindowClass(const char *_name, WNDPROC _wndproc) : + wndproc(_wndproc), atom(0), classname(_name) +{ + Register(); +} + +CWindow::CWindowClass::~CWindowClass() +{ + UnregisterClass(classname.c_str(), GetModuleHandle(NULL)); +} + +void CWindow::CWindowClass::Register() +{ + WNDCLASSEX wndclass; + memset(&wndclass, 0, sizeof(wndclass)); + wndclass.cbSize = sizeof(wndclass); + wndclass.style = 0; + wndclass.lpfnWndProc = wndproc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = GetModuleHandle(NULL); + wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = classname.c_str(); + wndclass.hIconSm = NULL; + atom = RegisterClassEx(&wndclass); + if (atom == 0) + throw win32_error("RegisterClassEx failed"); +} + +CWindow::CWindow(const char *_title) : title(_title), hwnd(NULL), parent(NULL), bounds(), owndproc(NULL), showing(FALSE) +{ + style = WS_CHILD; + exstyle = 0; +} + +HWND CWindow::CreateWindowHandle() +{ + HWND ret = CreateWindowEx( + exstyle, + GetClassName(), + title.c_str(), + style, + bounds.left, + bounds.top, + bounds.width, + bounds.height, + parent, + NULL, + GetModuleHandle(NULL), + 0 + ); + if (ret == NULL) + throw win32_error("CreateWindowEx failed"); + return ret; +} + +void CWindow::Create() +{ + if (hwnd != NULL) + return; + hwnd = CreateWindowHandle(); + if (hwnd == NULL) + throw win32_error("Could not create window"); + + // Reset the error code + DWORD err = 0; + SetLastError(err); + + // Attach the object reference to the window handle + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this); + err = GetLastError(); + if (err != 0) + throw win32_error("SetWindowLongPtr failed",err); + + // Set the window proc + owndproc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WindowProc); + err = GetLastError(); + if (err != 0) + throw win32_error("SetWindowLongPtr failed",err); +} + +const char *CWindow::GetClassName() +{ + return windowClass.GetClassName(); +} + +LRESULT CALLBACK CWindow::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MessageDebug::debug(hwnd, uMsg, wParam, lParam, __FUNCTION__); + CWindow* window = (CWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (window != NULL) + return window->Dispatch(hwnd, uMsg, wParam, lParam); + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +LRESULT CWindow::Dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_SIZE: + bounds.width = LOWORD(lParam); + bounds.height = LOWORD(lParam); + break; + case WM_MOVE: + bounds.left = LOWORD(lParam); + bounds.top = LOWORD(lParam); + break; + case WM_DESTROY: + showing = FALSE; + break; + } + if (owndproc) + return CallWindowProc(owndproc, hwnd, uMsg, wParam, lParam); + else + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +void CWindow::Show() +{ + if (hwnd == NULL) + Create(); + ShowWindow(hwnd, SW_SHOWNORMAL); +} + +int CWindow::ShowModal() +{ + MSG msg; + BOOL bRet; + showing = TRUE; + Show(); + + while( showing && (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) + { + if (bRet == -1) + { + // handle the error and possibly exit + } + else + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return 0; +} + +void CWindow::SetLeft(int left) +{ + bounds.left = left; + if (hwnd) + if (!SetWindowPos(hwnd, NULL, + bounds.left, bounds.top, + 0, 0, + SWP_NOZORDER | SWP_NOSIZE)) + throw win32_error("SetWindowPos failed"); +} + +void CWindow::SetTop(int top) +{ + bounds.top = top; + if (hwnd) + if (!SetWindowPos(hwnd, NULL, + bounds.left, bounds.top, + 0, 0, + SWP_NOZORDER | SWP_NOSIZE)) + throw win32_error("SetWindowPos failed"); +} + +void CWindow::SetWidth(int width) +{ + bounds.width = width; + if (hwnd) + if (!SetWindowPos(hwnd, NULL, + 0, 0, + bounds.width, bounds.height, + SWP_NOZORDER | SWP_NOMOVE)) + throw win32_error("SetWindowPos failed"); +} +void CWindow::SetHeight(int height) +{ + bounds.height = height; + if (hwnd) + if (!SetWindowPos(hwnd, NULL, + 0, 0, + bounds.width, bounds.height, + SWP_NOZORDER | SWP_NOMOVE)) + throw win32_error("SetWindowPos failed"); +} + +void CWindow::SetBounds(int left, int top, int width, int height) +{ + bounds = CBoundary(left, top, width, height); + if (hwnd) + if (!SetWindowPos(hwnd, NULL, + bounds.left, bounds.top, + bounds.width, bounds.height, + SWP_NOZORDER)) + throw win32_error("SetWindowPos failed"); +} + +void CWindow::SetBounds(const RECT &rect) +{ + bounds = rect; + if (hwnd) + if (!SetWindowPos(hwnd, NULL, + bounds.left, bounds.top, + bounds.width, bounds.height, + SWP_NOZORDER)) + throw win32_error("SetWindowPos failed"); +} + +HWND CWindow::GetHandle() +{ + if (hwnd == NULL) + Create(); + return hwnd; +} + +void CWindow::SetParent(CWindow *window) +{ + parent = window->GetHandle(); + if (hwnd != NULL) + if (::SetParent(hwnd, parent) == NULL) + throw win32_error("SetParent failed"); + +} + +void CWindow::SetStyle(DWORD style) +{ + this->style = style; + SetLastError(0); + if (hwnd) + SetWindowLong(hwnd, GWL_STYLE, style); + int err = GetLastError(); + if (err != 0) + throw win32_error("SetWindowLong failed", err); +} + +void CWindow::SetExStyle(DWORD exstyle) +{ + this->exstyle = exstyle; + SetLastError(0); + if (hwnd) + SetWindowLong(hwnd, GWL_EXSTYLE, exstyle); + int err = GetLastError(); + if (err != 0) + throw win32_error("SetWindowWLong failed", err); +} diff --git a/window/window.h b/window/window.h new file mode 100755 index 0000000..73c6877 --- /dev/null +++ b/window/window.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#ifndef __WINDOW_H__ +#define __WINDOW_H__ + +#include <windows.h> +#include <string> + +class CDialog; +class CWindow +{ + friend class CDialog; + public: + struct CBoundary + { + int left; + int top; + int width; + int height; + CBoundary() : + left(0), top(0), width(0), height(0) {}; + CBoundary(int x, int y, int w, int h) : + left(x), top(y), width(w), height(h) {}; + CBoundary(const RECT &r) : + left(r.left), top(r.top), width(r.right-r.left), height(r.bottom-r.top) {}; + }; + class CWindowClass + { + private: + WNDPROC wndproc; + ATOM atom; + std::string classname; + protected: + void Register(); + public: + CWindowClass(const char *name, WNDPROC wndproc); + ~CWindowClass(); + const char *GetClassName() { return classname.c_str(); }; + }; + private: + static CWindowClass windowClass; + + std::string title; + DWORD exstyle; + DWORD style; + CBoundary bounds; + HWND hwnd; + HWND parent; + WNDPROC owndproc; + + BOOL showing; + + protected: + + virtual const char *GetClassName(); + virtual HWND CreateWindowHandle(); + static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + public: + CWindow(const char *title); + virtual void Create(); + + virtual int ShowModal(); + + void Show(); + void Hide(); + + void SetWidth(int width); + void SetHeight(int height); + void SetLeft(int left); + void SetTop(int top); + int GetWidth() { return bounds.width; }; + int GetHeight() { return bounds.height; }; + int GetLeft() { return bounds.left; }; + int GetTop() { return bounds.top; }; + + void SetBounds(int left, int top, int width, int height); + void SetBounds(const RECT &rect); + + void SetStyle(DWORD style); + DWORD GetStyle() { return style; }; + + void SetExStyle(DWORD exstyle); + DWORD GetExStyle() { return exstyle; }; + + HWND GetHandle(); + void SetParent(CWindow *window); + + virtual LRESULT Dispatch(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + +#endif diff --git a/window/wizard.cc b/window/wizard.cc new file mode 100755 index 0000000..08d5a95 --- /dev/null +++ b/window/wizard.cc @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#include "wizard.h" +#include "util.h" + +CWizard::CWizard() : pages() +{ +}; + +void CWizard::AddPage(const PROPSHEETPAGE &page) +{ + pages.push_back(page); +} + +void CWizard::AddPage(const char *page, HINSTANCE instance) +{ + PROPSHEETPAGE psp; + if (instance == NULL) + instance = GetModuleHandle(NULL); + + memset(&psp, 0, sizeof(psp)); + psp.dwSize = sizeof(PROPSHEETPAGE); + psp.dwFlags = PSP_DEFAULT; + psp.hInstance = instance; + psp.pszTemplate = page; + psp.pfnDlgProc = WizardDialogProc; + psp.lParam = (LPARAM)this; + + AddPage(psp); +} + +void CWizard::AddPage(DWORD id, DWORD title, DWORD subtitle, HINSTANCE instance) +{ + PROPSHEETPAGE psp; + if (instance == NULL) + instance = GetModuleHandle(NULL); + + memset(&psp, 0, sizeof(psp)); + psp.dwSize = sizeof(PROPSHEETPAGE); + psp.dwFlags = PSP_DEFAULT; +#if _WIN32_IE >= 0x0500 + if (title != 0) + { + psp.dwFlags |= PSP_USEHEADERTITLE; + psp.pszHeaderTitle = MAKEINTRESOURCE(title); + } + if (subtitle != 0) + { + psp.dwFlags |= PSP_USEHEADERSUBTITLE; + psp.pszHeaderSubTitle = MAKEINTRESOURCE(subtitle); + } +#endif + + psp.hInstance = instance; + psp.pszTemplate = MAKEINTRESOURCE(id); + psp.pfnDlgProc = WizardDialogProc; + psp.lParam = (LPARAM)this; + + AddPage(psp); +} + +HWND CWizard::CreateWindowHandle() +{ + PROPSHEETHEADER psh; + HWND ret; + + PrepareSheetHeader(psh, FALSE); + ret = (HWND)PropertySheet(&psh); + free(psh.phpage); + if (ret == NULL) + throw win32_error("PropertySheet failed"); + return ret; +} + +int CWizard::ShowModal() +{ + PROPSHEETHEADER psh; + int ret; + + PrepareSheetHeader(psh, TRUE); + ret = PropertySheet(&psh); + free(psh.phpage); + return ret; +} + +void CWizard::PrepareSheetHeader(PROPSHEETHEADER &psh, BOOL modal) +{ + HPROPSHEETPAGE *phpage = (HPROPSHEETPAGE*)malloc(pages.size() * sizeof(HPROPSHEETPAGE)); + DWORD modeflag; + + if (modal) + modeflag = 0; + else + modeflag = PSH_MODELESS; + + for (unsigned i = 0; i < pages.size(); i++) + { + phpage[i] = CreatePropertySheetPage(&pages[i]); + if (phpage[i] == NULL) + { + DWORD err = GetLastError(); + free(phpage); + throw win32_error("CreatePropertySheetPage failed", err); + } + } + + memset(&psh, 0, sizeof(psh)); + psh.dwSize = sizeof(PROPSHEETHEADER); +#if _WIN32_IE >= 0x0500 + psh.dwFlags = PSH_WIZARD97 | modeflag; +#else + psh.dwFlags = PSH_WIZARD | modeflag; +#endif + psh.hwndParent = NULL; + psh.hInstance = GetModuleHandle(NULL); + psh.pszIcon = NULL; + psh.pszCaption = (LPSTR) "Cell Properties"; + psh.nPages = pages.size(); + psh.nStartPage = 0; + psh.phpage = phpage; + psh.pfnCallback = NULL; +} + +DWORD CWizard::PageID(unsigned index) +{ + if (index < pages.size() && IS_INTRESOURCE(pages[index].pszTemplate)) + return (DWORD)pages[index].pszTemplate; + return (DWORD)-1; +} + +unsigned CWizard::PageIndex(PROPSHEETPAGE *psp) +{ + for (unsigned i = 0; i < pages.size(); i++) + { + if (IS_INTRESOURCE(psp->pszTemplate) || IS_INTRESOURCE(pages[i].pszTemplate )) + { + if (psp->pszTemplate == pages[i].pszTemplate) + return i; + } + else if (psp->pszTemplate && pages[i].pszTemplate) + { + if (strcmp(psp->pszTemplate, pages[i].pszTemplate) == 0) + return i; + } + } + return (unsigned)-1; +} + +INT_PTR CWizard::DlgDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return CBaseDialog::DlgDispatch(hwndDlg, uMsg, wParam, lParam); +} + +INT_PTR CWizard::PageDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, PROPSHEETPAGE *psp) +{ + LPNMHDR pnmh = (LPNMHDR)lParam; + DWORD flags; + unsigned pageindex; + switch (uMsg) + { + case WM_NOTIFY: + switch (pnmh->code) + { + case PSN_SETACTIVE: +#ifdef _DEBUG + printf("PSN_SETACTIVE %d\n", PageIndex(psp)); +#endif + pageindex = PageIndex(psp); + if (pageindex != (unsigned)-1) + { + flags = 0; + if (pageindex > 0) + flags |= PSWIZB_BACK; + if ((unsigned)pageindex + 1 == pages.size()) + flags |= PSWIZB_FINISH; + if ((unsigned)pageindex + 1 < pages.size()) + flags |= PSWIZB_NEXT; + PropSheet_SetWizButtons(GetParent(hwndDlg), flags); + } + WizardActivate(hwndDlg, pageindex); + break; + case PSN_WIZNEXT: + if (WizardNext(hwndDlg, PageIndex(psp))) + return TRUE; + break; + case PSN_WIZBACK: + if (WizardBack(hwndDlg, PageIndex(psp))) + return TRUE; + break; + case PSN_WIZFINISH: + if (WizardFinish(hwndDlg, PageIndex(psp))) + return TRUE; + DestroyWindow(GetParent(hwndDlg)); + case PSN_RESET: + if (WizardReset(hwndDlg, PageIndex(psp))) + return TRUE; + DestroyWindow(GetParent(hwndDlg)); + break; + } + } + return DlgDispatch(hwndDlg, uMsg, wParam, lParam); +} + + +INT_PTR CALLBACK CWizard::WizardDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MessageDebug::debug(hwndDlg, uMsg, wParam, lParam, __FUNCTION__); + PROPSHEETPAGE *psp = (PROPSHEETPAGE*)lParam; + switch (uMsg) + { + case WM_INITDIALOG: + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)psp); + break; + } + psp = (PROPSHEETPAGE*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + CWizard* wizard = psp?(CWizard*)psp->lParam:NULL; + if (wizard != NULL) + return wizard->PageDispatch(hwndDlg, uMsg, wParam, lParam, psp); + return FALSE; +} diff --git a/window/wizard.h b/window/wizard.h new file mode 100755 index 0000000..fc1beb9 --- /dev/null +++ b/window/wizard.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2005 Alexander Gottwald + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ +#ifndef __WIZARD_H__ +#define __WIZARD_H__ + +#include "dialog.h" +#include <vector> + +#define _WIN32_IE 0x0500 +#include <prsht.h> + +class CWizard : public CBaseDialog +{ + private: + std::vector<PROPSHEETPAGE> pages; + void PrepareSheetHeader(PROPSHEETHEADER &psh, BOOL modal); + protected: + virtual HWND CreateWindowHandle(); + static INT_PTR CALLBACK WizardDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual INT_PTR DlgDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual INT_PTR PageDispatch(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam, PROPSHEETPAGE *psp); + virtual unsigned PageIndex(PROPSHEETPAGE *psp); + virtual DWORD PageID(unsigned index); + virtual BOOL WizardNext(HWND hwndDlg, unsigned index) { return FALSE; } + virtual BOOL WizardBack(HWND hwndDlg, unsigned index) { return FALSE; } + virtual BOOL WizardFinish(HWND hwndDlg, unsigned index) { return FALSE; } + virtual BOOL WizardReset(HWND hwndDlg, unsigned index) { return FALSE; } + virtual BOOL WizardActivate(HWND hwndDlg, unsigned index) { return FALSE; } + public: + CWizard(); + void AddPage(const PROPSHEETPAGE &page); + void AddPage(const char *page, HINSTANCE instance = NULL); + void AddPage(DWORD id, DWORD title, DWORD subtitle, HINSTANCE instance = NULL); + virtual int ShowModal(); +}; +#endif |