OpenClonk
C4GfxErrorDlg.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2012-2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 /* Functions for displaying a settings dialogue to users when the graphics system failed */
17 
18 #include "C4Include.h"
19 
20 #ifdef _WIN32
21 
22 #include "res/resource.h"
23 #include "C4Version.h"
24 #include "game/C4Application.h"
26 #include "gui/C4GfxErrorDlg.h"
27 
28 #include "graphics/C4Draw.h"
29 
30 static int edittext_toi(HWND hWnd, int field)
31 {
32  WCHAR buf[512]; buf[511] = 0;
33  GetDlgItemTextW(hWnd,field,buf,509);
34  StdStrBuf data(buf);
35  const char* bufp = data.getData();
36  while(*bufp == ' ') ++bufp;
37  int res = strtol(bufp, nullptr, 0);
38  if(errno != ERANGE)
39  return res;
40  return -1;
41 }
42 
43 static INT_PTR CALLBACK GfxErrProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
44 {
45  switch(Msg)
46  {
47  case WM_INITDIALOG:
48  // Set Icon, Caption and static Texts
49  SendMessage(hWnd,WM_SETICON,ICON_BIG,(LPARAM)LoadIcon(Application.GetInstance(),MAKEINTRESOURCE(IDI_00_C4X)));
50  SendMessage(hWnd,WM_SETICON,ICON_SMALL,(LPARAM)LoadIcon(Application.GetInstance(),MAKEINTRESOURCE(IDI_00_C4X)));
51  SetWindowTextW(hWnd, GetWideChar(C4ENGINECAPTION));
52  SetDlgItemTextW(hWnd,IDC_GFXERR_MSG ,GetWideChar(LoadResStr("IDS_MSG_GFXERR_TXT")));
53  SetDlgItemTextW(hWnd,IDC_GFXERR_RES ,GetWideChar(LoadResStr("IDS_CTL_RESOLUTION")));
54  SetDlgItemTextW(hWnd,IDC_GFXERR_FSCRN,GetWideChar(LoadResStr("IDS_MSG_FULLSCREEN")));
55  SetDlgItemTextW(hWnd,IDCANCEL ,GetWideChar(LoadResStr("IDS_DLG_EXIT")));
56  SetDlgItemTextW(hWnd,IDOK ,GetWideChar(LoadResStr("IDS_BTN_RESTART")));
57  // Set Options
58  SendMessage(GetDlgItem(hWnd, IDC_GFXERR_FSCRN), BM_SETCHECK, Config.Graphics.Windowed?0:1, 0);
59  SetDlgItemTextW(hWnd,IDC_GFXERR_XINP ,FormatString("%d",Config.Graphics.ResX).GetWideChar());
60  SetDlgItemTextW(hWnd,IDC_GFXERR_YINP ,FormatString("%d",Config.Graphics.ResY).GetWideChar());
61  return TRUE;
62 
63  case WM_DESTROY:
64  EndDialog(hWnd,1);
65  return TRUE;
66 
67  case WM_COMMAND:
68  {
69  switch(LOWORD(wParam))
70  {
71  case IDCANCEL:
72  EndDialog(hWnd,1);
73  return TRUE;
74  case IDC_GFXERR_FSCRN:
75  case IDC_GFXERR_XINP:
76  case IDC_GFXERR_YINP:
77  { // Handle Resolution values
78  if(SendMessage(GetDlgItem(hWnd, IDC_GFXERR_FSCRN),BM_GETCHECK,0,0) == BST_CHECKED)
79  {
80  int resx = edittext_toi(hWnd,IDC_GFXERR_XINP);
81  int resy = edittext_toi(hWnd,IDC_GFXERR_YINP);
82  if(resx < 1 || resy < 1) // res. will be 0 if the user supplies an invalid value
83  SetDlgItemTextW(hWnd,IDC_GFXERR_INVAL,GetWideChar(LoadResStr("IDS_MSG_GFXERR_RESINVAL")));
84  else
85  {
86  // Check if res is in list of supportet
87  bool found = false;
88  int32_t idx = 0, iXRes, iYRes, iBitDepth;
89  while (Application.GetIndexedDisplayMode(idx++, &iXRes, &iYRes, &iBitDepth, nullptr, Config.Graphics.Monitor))
90  if (iBitDepth == C4Draw::COLOR_DEPTH)
91  if(iXRes == resx && iYRes == resy)
92  {
93  found = true;
94  break;
95  }
96  SetDlgItemTextW(hWnd,IDC_GFXERR_INVAL,found?L"":GetWideChar(LoadResStr("IDS_MSG_GFXERR_RESNOTFOUND")));
97  }
98  }
99  else
100  SetDlgItemTextW(hWnd,IDC_GFXERR_INVAL,L"");
101  return TRUE;
102  }
103  case IDOK:
104  {
105  int resx = edittext_toi(hWnd,IDC_GFXERR_XINP);
106  int resy = edittext_toi(hWnd,IDC_GFXERR_YINP);
107  if(resx < 1 || resy < 1) break;
108  Config.Graphics.Windowed = !(SendMessage(GetDlgItem(hWnd, IDC_GFXERR_FSCRN),BM_GETCHECK,0,0) == BST_CHECKED);
109  Config.Graphics.ResX = resx;
110  Config.Graphics.ResY = resy;
111  Config.Save();
112  TCHAR selfpath[4096];
113  GetModuleFileName(nullptr, selfpath, 4096);
114  STARTUPINFOW siStartupInfo;
115  PROCESS_INFORMATION piProcessInfo;
116  memset(&siStartupInfo, 0, sizeof(siStartupInfo));
117  memset(&piProcessInfo, 0, sizeof(piProcessInfo));
118  siStartupInfo.cb = sizeof(siStartupInfo);
119  if (CreateProcessW(selfpath, nullptr,
120  nullptr, nullptr, FALSE, 0, nullptr, Config.General.ExePath.GetWideChar(), &siStartupInfo, &piProcessInfo))
121  {
122  CloseHandle(piProcessInfo.hProcess);
123  CloseHandle(piProcessInfo.hThread);
124  }
125  EndDialog(hWnd,2);
126  return TRUE;
127  }
128  }
129  }
130  }
131  return FALSE;
132 }
133 
134 void ShowGfxErrorDialog()
135 {
136  // Application.Close will eventually post a quit message. We need to discard
137  // that, so DialogBox() doesn't immediately exit.
138  auto msg = MSG();
139  while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != 0)
140  {
141  if (msg.message == WM_QUIT) break;
142  TranslateMessage(&msg);
143  DispatchMessage(&msg);
144  }
145 
146  int ret = DialogBox(Application.GetInstance(), MAKEINTRESOURCE(IDD_GFXERROR), nullptr, GfxErrProcedure);
147  if (ret == 0 || ret == -1)
148  {
149  LPVOID lpMsgBuf;
150  DWORD err = GetLastError();
151  FormatMessage(
152  FORMAT_MESSAGE_ALLOCATE_BUFFER |
153  FORMAT_MESSAGE_FROM_SYSTEM |
154  FORMAT_MESSAGE_IGNORE_INSERTS,
155  nullptr,
156  err,
157  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
158  (LPTSTR) &lpMsgBuf,
159  0, nullptr );
160  LogF("Error in GfxErrorDlg: %d - %s", err, StdStrBuf((wchar_t*)lpMsgBuf).getData());
161  LocalFree(lpMsgBuf);
162  }
163 
164  // If we discarded a quit message, re-post it now
165  if (msg.message == WM_QUIT)
166  PostQuitMessage(msg.wParam);
167 }
168 
169 #else
170 void ShowGfxErrorDialog(){} // To be implemented? It's mainly a windows (users') problem.
171 #endif
C4Config Config
Definition: C4Config.cpp:930
void ShowGfxErrorDialog()
C4Application Application
Definition: C4Globals.cpp:44
const char * LoadResStr(const char *id)
Definition: C4Language.h:83
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:262
StdStrBuf::wchar_t_holder GetWideChar(const char *utf8, bool double_null_terminate=false)
uint32_t DWORD
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
bool GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor)
Definition: C4AppSDL.cpp:335
StdCopyStrBuf ExePath
Definition: C4Config.h:54
int32_t ResX
Definition: C4Config.h:104
int32_t ResY
Definition: C4Config.h:104
int32_t Windowed
Definition: C4Config.h:107
int32_t Monitor
Definition: C4Config.h:112
C4ConfigGeneral General
Definition: C4Config.h:255
bool Save()
Definition: C4Config.cpp:439
C4ConfigGraphics Graphics
Definition: C4Config.h:257
static constexpr int COLOR_DEPTH
Definition: C4Draw.h:89
#define IDD_GFXERROR
Definition: resource.h:68
#define IDC_GFXERR_XINP
Definition: resource.h:55
#define IDC_GFXERR_MSG
Definition: resource.h:52
#define IDC_GFXERR_YINP
Definition: resource.h:57
#define IDC_GFXERR_RES
Definition: resource.h:53
#define IDI_00_C4X
Definition: resource.h:69
#define IDC_GFXERR_FSCRN
Definition: resource.h:58
#define IDC_GFXERR_INVAL
Definition: resource.h:59