GUIFramework 1.1.0
Framework for desktop GUI applications in C++.
Loading...
Searching...
No Matches
BaseComboBox.cpp
Go to the documentation of this file.
1#include "BaseComboBox.h"
2
3#include "GUIFramework.h"
4
8
9#pragma warning(disable: 4018)
10#pragma warning(disable: 4267)
11
12#pragma push_macro("min")
13#pragma push_macro("max")
14#undef min
15#undef max
16
17using namespace std;
18
19namespace gui_framework
20{
21 LRESULT BaseComboBox::windowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool& isUsed)
22 {
23 if (message == WM_COMMAND && id == LOWORD(wparam))
24 {
25 switch (HIWORD(wparam))
26 {
27 case CBN_SELCHANGE:
29 {
30 isUsed = true;
31
32 onSelectionChange(*this);
33 }
34
35 return 0;
36
37 default:
38 break;
39 }
40 }
41
42 isUsed = false;
43
44 return -1;
45 }
46
47 void BaseComboBox::loadOnSelectionChangeFromModule(function<void(BaseComboBox&)>& onSelectionChange, const string& functionName, const string& moduleName)
48 {
49 GUIFramework& instance = GUIFramework::get();
50 const HMODULE& module = instance.getModules().at(moduleName);
51
52 comboBoxCallbackSignature tem = reinterpret_cast<comboBoxCallbackSignature>(GetProcAddress(module, functionName.data()));
53
54 if (!tem)
55 {
56 throw exceptions::CantFindFunctionFromModuleException(functionName, moduleName, __FILE__, __FUNCTION__, __LINE__);
57 }
58
60 }
61
62 BaseComboBox::BaseComboBox(const wstring& comboBoxName, const utility::ComponentSettings& settings, const styles::ComboBoxStyles& styles, BaseComposite* parent) :
64 (
65 standard_classes::comboBox,
66 comboBoxName,
67 settings,
68 styles,
69 parent
70 ),
71 IResizableComponent
72 (
73 handle,
74 parent ? parent->getHandle() : nullptr,
75 true
76 ),
77 requiredSize{ 0, 0 }
78 {
79
80 }
81
82 LRESULT BaseComboBox::addValue(const wstring& value)
83 {
84 LRESULT result = SendMessageW(handle, CB_ADDSTRING, NULL, reinterpret_cast<LPARAM>(value.data()));
85
86 if (result == CB_ERR)
87 {
88 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
89 }
90 else if (result == CB_ERRSPACE)
91 {
92 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__, exception_messages::notEnoughSpace);
93 }
94
96
97 return result;
98 }
99
100 LRESULT BaseComboBox::addValues(const vector<wstring>& values)
101 {
102 LRESULT result = 0;
103
104 for (const wstring& value : values)
105 {
106 result = this->addValue(value);
107 }
108
109 return result;
110 }
111
112 LRESULT BaseComboBox::removeValue(size_t index)
113 {
114 LRESULT result = SendMessageW(handle, CB_DELETESTRING, index, NULL);
115
116 if (result == CB_ERR)
117 {
118 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
119 }
120
122
123 return result;
124 }
125
126 LRESULT BaseComboBox::insertValue(const wstring& value, LRESULT index)
127 {
128 LRESULT result = SendMessageW(handle, CB_INSERTSTRING, index, reinterpret_cast<LPARAM>(value.data()));
129
130 if (result == CB_ERR)
131 {
132 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
133 }
134 else if (result == CB_ERRSPACE)
135 {
136 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__, exception_messages::notEnoughSpace);
137 }
138
140
141 return result;
142 }
143
144 LRESULT BaseComboBox::changeValue(const wstring& newValue, LRESULT index)
145 {
146 LRESULT result = SendMessageW(handle, CB_SETITEMDATA, index, reinterpret_cast<LPARAM>(newValue.data()));
147
148 if (result == CB_ERR)
149 {
150 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
151 }
152
154
155 return result;
156 }
157
158 LRESULT BaseComboBox::findSubstring(const wstring& substringToFind)
159 {
160 LRESULT findedIndex = SendMessageW(handle, CB_FINDSTRING, 0, reinterpret_cast<LPARAM>(substringToFind.data()));
161
162 if (findedIndex == CB_ERR)
163 {
164 throw exceptions::SelectListException(__FUNCTION__, findedIndex, __FILE__, __FUNCTION__, __LINE__);
165 }
166
167 return findedIndex;
168 }
169
170 LRESULT BaseComboBox::findString(const wstring& stringToFind)
171 {
172 LRESULT findedIndex = SendMessageW(handle, CB_FINDSTRINGEXACT, 0, reinterpret_cast<LPARAM>(stringToFind.data()));
173
174 if (findedIndex == CB_ERR)
175 {
176 throw exceptions::SelectListException(__FUNCTION__, findedIndex, __FILE__, __FUNCTION__, __LINE__);
177 }
178
179 return findedIndex;
180 }
181
182 wstring BaseComboBox::getValue(size_t index) const
183 {
184 wstring result;
185 LRESULT size = SendMessageW(handle, CB_GETLBTEXTLEN, index, NULL);
186
187 if (size == CB_ERR)
188 {
189 throw exceptions::SelectListException(__FUNCTION__, size, __FILE__, __FUNCTION__, __LINE__);
190 }
191
192 result.resize(++size);
193
194 LRESULT errorCode = SendMessageW(handle, CB_GETLBTEXT, index, reinterpret_cast<LPARAM>(result.data()));
195
196 if (errorCode == CB_ERR)
197 {
198 throw exceptions::SelectListException(__FUNCTION__, errorCode, __FILE__, __FUNCTION__, __LINE__);
199 }
200
201 result.pop_back();
202
203 return result;
204 }
205
207 {
208 return SendMessageW(handle, CB_GETCURSEL, NULL, NULL);
209 }
210
211 LRESULT BaseComboBox::setCurrentSelection(LRESULT index) const
212 {
213 LRESULT result = SendMessageW(handle, CB_SETCURSEL, index, NULL);
214
215 if (result == CB_ERR)
216 {
217 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
218 }
219
220 return result;
221 }
222
223 LRESULT BaseComboBox::size() const
224 {
225 LRESULT result = SendMessageW(handle, CB_GETCOUNT, NULL, NULL);
226
227 if (result == CB_ERR)
228 {
229 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
230 }
231
232 return result;
233 }
234
236 {
237 SendMessageW(handle, CB_RESETCONTENT, NULL, NULL);
238 }
239
240 void BaseComboBox::setSortingMode(bool isSorting)
241 {
242 isSorting ?
243 SetWindowLongPtrW(handle, GWL_STYLE, GetWindowLongPtrW(handle, GWL_STYLE) | CBS_SORT) :
244 SetWindowLongPtrW(handle, GWL_STYLE, GetWindowLongPtrW(handle, GWL_STYLE) ^ CBS_SORT);
245 }
246
247 LRESULT BaseComboBox::setItemHeight(itemHeightEnum value, uint16_t height)
248 {
249 LRESULT result = SendMessageW(handle, CB_SETITEMHEIGHT, static_cast<WPARAM>(value), height);
250
251 if (result == CB_ERR)
252 {
253 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
254 }
255
256 return result;
257 }
258
259 LRESULT BaseComboBox::setDroppedWidth(uint16_t width)
260 {
261 LRESULT result = SendMessageW(handle, CB_SETDROPPEDWIDTH, width, NULL);
262
263 if (result == CB_ERR)
264 {
265 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
266 }
267
268 return result;
269 }
270
271 void BaseComboBox::setOnSelectionChange(const function<void(BaseComboBox&)>& onSelectionChange)
272 {
274
275 functionName.clear();
276 moduleName.clear();
277 }
278
279 void BaseComboBox::setOnSelectionChange(const string& functionName, const string& moduleName)
280 {
281 GUIFramework& instance = GUIFramework::get();
282 const HMODULE& module = instance.getModules().at(moduleName);
283
284 comboBoxCallbackSignature tem = reinterpret_cast<comboBoxCallbackSignature>(GetProcAddress(module, functionName.data()));
285
286 if (!tem)
287 {
288 throw exceptions::CantFindFunctionFromModuleException(functionName, moduleName, __FILE__, __FUNCTION__, __LINE__);
289 }
290
291 onSelectionChange = tem;
292
293 this->functionName = functionName;
294 this->moduleName = moduleName;
295 }
296
298 {
299 LRESULT result = SendMessageW(handle, CB_GETITEMHEIGHT, static_cast<WPARAM>(value), NULL);
300
301 if (result == CB_ERR)
302 {
303 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
304 }
305
306 return result;
307 }
308
310 {
311 LRESULT result = SendMessageW(handle, CB_GETDROPPEDWIDTH, NULL, NULL);
312
313 if (result == CB_ERR)
314 {
315 throw exceptions::SelectListException(__FUNCTION__, result, __FILE__, __FUNCTION__, __LINE__);
316 }
317
318 return result;
319 }
320
321 void BaseComboBox::resize(uint16_t width, uint16_t height)
322 {
323 if (autoResize && !blockResize)
324 {
325 LRESULT currentSize = this->size();
326 HDC deviceContext = GetDC(handle);
327 int heightSum = 0;
328
329 if (currentSize == CB_ERR || !currentSize)
330 {
331 double widthCoefficient = static_cast<double>(width) / parentWidth;
332
333 MoveWindow
334 (
335 handle,
336 static_cast<int>(desiredX * widthCoefficient),
337 static_cast<int>(desiredY * (static_cast<double>(height) / parentHeight)),
338 static_cast<int>(desiredWidth * widthCoefficient),
340 true
341 );
342
343 ShowWindow(handle, SW_SHOW);
344
345 return;
346 }
347
348 for (size_t i = 0; i < currentSize; i++)
349 {
350 wstring value = this->getValue(i);
351 SIZE valueSizes;
352
353 if (GetTextExtentPoint32W(deviceContext, value.data(), value.size(), &valueSizes))
354 {
355 if (valueSizes.cx > requiredSize.cx)
356 {
357 requiredSize.cx = valueSizes.cx;
358 }
359
360 if (valueSizes.cy > requiredSize.cy)
361 {
362 requiredSize.cy = valueSizes.cy;
363 }
364
365 heightSum += valueSizes.cy;
366 }
367 }
368
369 this->setItemHeight(itemHeightEnum::forAllItems, static_cast<uint16_t>(requiredSize.cy));
370
371 MoveWindow
372 (
373 handle,
374 static_cast<int>(desiredX * (static_cast<double>(width) / parentWidth)),
375 static_cast<int>(desiredY * (static_cast<double>(height) / parentHeight)),
376 max(requiredSize.cx + standard_sizes::comboBoxAdditionalWidth, static_cast<long>(desiredWidth * (static_cast<double>(width) / parentWidth))),
377 heightSum + requiredSize.cy * 2,
378 true
379 );
380
381 ShowWindow(handle, SW_SHOW);
382 }
383 }
384
385 void BaseComboBox::setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue)
386 {
387 __utility::throwNotImplementedException(__FUNCTION__, "BaseComboBox"sv);
388 }
389
390 void BaseComboBox::setTextColor(uint8_t red, uint8_t green, uint8_t blue)
391 {
392 __utility::throwNotImplementedException(__FUNCTION__, "BaseComboBox"sv);
393 }
394
395 json::JSONBuilder BaseComboBox::getStructure() const
396 {
397 using json::utility::jsonObject;
398
399 uint32_t codepage = ISerializable::getCodepage();
400 json::JSONBuilder builder = BaseComponent::getStructure();
401 jsonObject& current = get<jsonObject>(builder[utility::to_string(windowName, codepage)]);
402 vector<jsonObject> values;
403 LRESULT currentSize = this->size();
404
405 if (functionName.size())
406 {
407 current.data.push_back({ "functionName"s, functionName });
408
409 current.data.push_back({ "moduleName"s, moduleName });
410
411 current.data.push_back({ "pathToModule"s, GUIFramework::get().getModulesPaths().at(moduleName) });
412 }
413
414 if (currentSize > 0)
415 {
416 for (size_t i = 0; i < static_cast<size_t>(currentSize); i++)
417 {
418 json::utility::appendArray(utility::to_string(this->getValue(i), codepage), values);
419 }
420
421 current.data.push_back({ "comboBoxValues"s, move(values) });
422 }
423
424 return builder;
425 }
426}
427
428#pragma pop_macro("min")
429#pragma pop_macro("max")
Base class for all combo boxes.
std::function< void(BaseComboBox &)> onSelectionChange
LRESULT setDroppedWidth(uint16_t width)
void setOnSelectionChange(const std::function< void(BaseComboBox &)> &onSelectionChange)
Set callback function with on selection change event.
LRESULT addValue(const std::wstring &value)
virtual LRESULT insertValue(const std::wstring &value, LRESULT index)
std::wstring getValue(size_t index) const
LRESULT setCurrentSelection(LRESULT index) const
virtual json::JSONBuilder getStructure() const override
virtual void resize(uint16_t width, uint16_t height) override
virtual LRESULT changeValue(const std::wstring &newValue, LRESULT index)
virtual LRESULT windowMessagesHandle(HWND handle, UINT message, WPARAM wparam, LPARAM lparam, bool &isUsed) final override
BaseComboBox(const std::wstring &comboBoxName, const utility::ComponentSettings &settings, const styles::ComboBoxStyles &styles, BaseComposite *parent)
LRESULT addValues(const std::vector< std::wstring > &values)
virtual void setBackgroundColor(uint8_t red, uint8_t green, uint8_t blue) final override
Not implemented.
void setSortingMode(bool isSorting)
virtual void setTextColor(uint8_t red, uint8_t green, uint8_t blue) final override
Not implemented.
static void loadOnSelectionChangeFromModule(std::function< void(BaseComboBox &)> &onSelectionChange, const std::string &functionName, const std::string &moduleName)
Load function from module.
LRESULT findSubstring(const std::wstring &substringToFind)
Find not case sensitive substring.
LRESULT findString(const std::wstring &stringToFind)
Find not case sensitive string.
LRESULT removeValue(size_t index)
LRESULT getItemHeight(itemHeightEnum value) const
LRESULT setItemHeight(itemHeightEnum value, uint16_t height)
LRESULT getCurrentSelectionIndex() const
Base class for all windows, controls, etc.
virtual json::JSONBuilder getStructure() const override
const std::wstring windowName
Base class for all windows that has children windows.
Singleton with GUIFramework settings and some functionality.
const std::unordered_map< std::string, std::string > & getModulesPaths() const
Get all loaded modules paths.
const std::unordered_map< std::string, HMODULE, localization::utility::StringViewHash, localization::utility::StringViewEqual > & getModules() const
Get all loaded modules.
static GUIFramework & get()
Singleton instance access.
Exception for all list classes exceptions.
Base class for combo box styles.
void throwNotImplementedException(string_view methodName, string_view className)
Definition Utility.cpp:186
constexpr std::string_view notEnoughSpace
string to_string(wstring_view stringToConvert, uint32_t codepage)
Definition Utility.cpp:41
void(*)(BaseComboBox &) comboBoxCallbackSignature
Used in notification events in combo box.