1
2
3
4
5
6 using System;
7 using System.Collections;
8 using System.IO;
9
10 namespace System.Windows.API
11 {
12 public const long ERROR_DUPLICATE_CODE_MAPPING = -2;
13 public const long ERROR_CODE_NOT_FOUND = -1;
14 public const long ERROR_OUT_OF_RESOURCES = 0;
15 public const long ERROR_FILE_NOT_FOUND = 1;
16 public const long ERROR_PATH_NOT_FOUND = 2;
17 public const long ERROR_BAD_FORMAT = 3;
18 public const long SE_ERR_ACCESSDENIED = 4;
19 public const long SE_ERR_ASSOCINCOMPLETE = 5;
20 public const long SE_ERR_DDEBUSY = 6;
21 public const long SE_ERR_DDEFAIL = 7;
22 public const long SE_ERR_DDETIMEOUT = 8;
23 public const long SE_ERR_DLLNOTFOUND = 9;
24 public const long SE_ERR_FNF = 10;
25 public const long SE_ERR_NOASSOC = 11;
26 public const long SE_ERR_OOM = 12;
27 public const long SE_ERR_PNF = 13;
28 public const long SE_ERR_SHARE = 14;
29
30 [nodiscard]
31 public Result<string> GetWindowsAPIErrorMessage(ulong errorCode)
32 {
33 wchar[4096] buffer;
34 WinFormatMessage(errorCode, &buffer[0]);
35 auto utf8Result = ToUtf8(wstring(&buffer[0]));
36 if (utf8Result.Error())
37 {
38 return Result<string>(ErrorId(utf8Result.GetErrorId()));
39 }
40 return Result<string>(utf8Result.Value());
41 }
42
43 [nodiscard]
44 public Result<void*> FindFirstChangeNotification(const string& directoryPath)
45 {
46 void* notificationHandle = WinFindFirstChangeNotification(directoryPath.Chars());
47 if (notificationHandle == null)
48 {
49 int errorId = WinAllocateWindowsError("find first change notification failed", WinGetLastError());
50 return Result<void*>(ErrorId(errorId));
51 }
52 return Result<void*>(notificationHandle);
53 }
54
55 [nodiscard]
56 public Result<bool> FindNextChangeNotification(void* notificationHandle)
57 {
58 bool result = WinFindNextChangeNotification(notificationHandle);
59 if (!result)
60 {
61 int errorId = WinAllocateWindowsError("find next change notification failed", WinGetLastError());
62 return Result<bool>(ErrorId(errorId));
63 }
64 return Result<bool>(true);
65 }
66
67 [nodiscard]
68 public Result<bool> FindCloseChangeNotification(void* notificationHandle)
69 {
70 bool result = WinFindCloseChangeNotification(notificationHandle);
71 if (!result)
72 {
73 int errorId = WinAllocateWindowsError("find close change notification failed", WinGetLastError());
74 return Result<bool>(ErrorId(errorId));
75 }
76 return Result<bool>(true);
77 }
78
79 [nodiscard]
80 public Result<void*> CreateEvent()
81 {
82 void* eventHandle = WinCreateEvent();
83 if (eventHandle == null)
84 {
85 int errorId = WinAllocateWindowsError("create event failed", WinGetLastError());
86 return Result<void*>(ErrorId(errorId));
87 }
88 return Result<void*>(eventHandle);
89 }
90
91 [nodiscard]
92 public Result<bool> SetEvent(void* eventHandle)
93 {
94 bool result = WinSetEvent(eventHandle);
95 if (!result)
96 {
97 int errorId = WinAllocateWindowsError("set event failed", WinGetLastError());
98 return Result<bool>(ErrorId(errorId));
99 }
100 return Result<bool>(true);
101 }
102
103 [nodiscard]
104 public Result<bool> ResetEvent(void* eventHandle)
105 {
106 bool result = WinResetEvent(eventHandle);
107 if (!result)
108 {
109 int errorId = WinAllocateWindowsError("reset event failed", WinGetLastError());
110 return Result<bool>(ErrorId(errorId));
111 }
112 return Result<bool>(true);
113 }
114
115 [nodiscard]
116 public Result<bool> WaitEvent(void* eventHandle)
117 {
118 bool result = WinWaitEvent(eventHandle);
119 if (!result)
120 {
121 int errorId = WinAllocateWindowsError("wait event failed", WinGetLastError());
122 return Result<bool>(ErrorId(errorId));
123 }
124 return Result<bool>(true);
125 }
126
127 [nodiscard]
128 public Result<bool> CloseHandle(void* handle)
129 {
130 bool result = WinCloseHandle(handle);
131 if (!result)
132 {
133 int errorId = WinAllocateWindowsError("close handle failed", WinGetLastError());
134 return Result<bool>(ErrorId(errorId));
135 }
136 return Result<bool>(true);
137 }
138
139 [nodiscard]
140 public Result<bool> CloseEvent(void* eventHandle)
141 {
142 return CloseHandle(eventHandle);
143 }
144
145 [nodiscard]
146 public Result<int> WaitForMultipleObjects(const List<void*>& handles)
147 {
148 int result = WinWaitForMultipleObjects(cast<uint>(handles.Count()), handles.Begin().Ptr());
149 if (result >= 0 && result <= handles.Count())
150 {
151 return Result<int>(result);
152 }
153 else
154 {
155 int errorId = WinAllocateWindowsError("wait for multiple objects failed", WinGetLastError());
156 return Result<int>(ErrorId(errorId));
157 }
158 }
159
160 [nodiscard]
161 public Result<bool> ShellExecute(const string& filePath)
162 {
163 long errorCode = 0;
164 bool succeeded = WinShellExecute(filePath.Chars(), errorCode);
165 if (!succeeded)
166 {
167 string errorMessage = "shell execution error for file \'" + filePath + "\': ";
168 string error = "out of resources";
169 switch (errorCode)
170 {
171 case ERROR_DUPLICATE_CODE_MAPPING:
172 {
173 error = "duplicate code mapping detected"; break;
174 }
175 case ERROR_CODE_NOT_FOUND:
176 {
177 error = "code not found"; break;
178 }
179 case ERROR_OUT_OF_RESOURCES:
180 {
181 error = "out of resources"; break;
182 }
183 case ERROR_FILE_NOT_FOUND:
184 {
185 error = "file not found"; break;
186 }
187 case ERROR_PATH_NOT_FOUND:
188 {
189 error = "path not found"; break;
190 }
191 case ERROR_BAD_FORMAT:
192 {
193 error = "invalid executable"; break;
194 }
195 case SE_ERR_ACCESSDENIED:
196 {
197 error = "access denied"; break;
198 }
199 case SE_ERR_ASSOCINCOMPLETE:
200 {
201 error = "invalid file association"; break;
202 }
203 case SE_ERR_DDEBUSY:
204 {
205 error = "DDE busy"; break;
206 }
207 case SE_ERR_DDEFAIL:
208 {
209 error = "DDE failed"; break;
210 }
211 case SE_ERR_DDETIMEOUT:
212 {
213 error = "DDE timeout"; break;
214 }
215 case SE_ERR_DLLNOTFOUND:
216 {
217 error = "DLL not found"; break;
218 }
219 case SE_ERR_FNF:
220 {
221 error = "file not found"; break;
222 }
223 case SE_ERR_NOASSOC:
224 {
225 error = "no association for this type of file"; break;
226 }
227 case SE_ERR_OOM:
228 {
229 error = "not enough memory"; break;
230 }
231 case SE_ERR_PNF:
232 {
233 error = "path not found"; break;
234 }
235 case SE_ERR_SHARE:
236 {
237 error = "sharing violation"; break;
238 }
239 }
240 errorMessage.Append(error);
241 int errorId = AllocateError(errorMessage);
242 return Result<bool>(ErrorId(errorId));
243 }
244 return Result<bool>(true);
245 }
246
247 [nodiscard]
248 public Result<ushort> RegisterWindowClass(const char* windowClassName, uint style, int backgroundColor)
249 {
250 ushort windowClass = WinRegisterWindowClass(windowClassName, style, backgroundColor);
251 if (windowClass == 0u)
252 {
253 int errorId = WinAllocateWindowsError("register window class failed", WinGetLastError());
254 return Result<ushort>(ErrorId(errorId));
255 }
256 return Result<ushort>(windowClass);
257 }
258
259 [nodiscard]
260 public Result<void*> CreateWindowByClassAtom(ushort windowClass, const char* windowName, long style, long exStyle, Point location, Size size, Control* parent)
261 {
262 void* parentHandle = null;
263 if (parent != null)
264 {
265 parentHandle = parent->Handle();
266 }
267 void* result = WinCreateWindowByClassAtom(windowClass, windowName, style, exStyle, location.x, location.y, size.w, size.h, parentHandle);
268 if (result == null)
269 {
270 int errorId = WinAllocateWindowsError("create window by class atom failed", WinGetLastError());
271 return Result<void*>(ErrorId(errorId));
272 }
273 else
274 {
275 return Result<void*>(result);
276 }
277 }
278
279 [nodiscard]
280 public Result<void*> CreateWindowByClassName(const char* windowClass, const char* windowName, long style, long exStyle, Point location, Size size, Control* parent)
281 {
282 void* parentHandle = null;
283 if (parent != null)
284 {
285 parentHandle = parent->Handle();
286 }
287 void* result = WinCreateWindowByClassName(windowClass, windowName, style, exStyle, location.x, location.y, size.w, size.h, parentHandle);
288 if (result == null)
289 {
290 int errorId = WinAllocateWindowsError("create window by class name failed", WinGetLastError());
291 return Result<void*>(ErrorId(errorId));
292 }
293 else
294 {
295 return Result<void*>(result);
296 }
297 }
298
299 [nodiscard]
300 public Result<bool> MoveWindow(void* windowHandle, const Point& location, const Size& size, bool repaint)
301 {
302 bool succeeded = WinMoveWindow(windowHandle, location.x, location.y, size.w, size.h, repaint);
303 if (!succeeded)
304 {
305 int errorId = WinAllocateWindowsError("move window failed", WinGetLastError());
306 return Result<bool>(ErrorId(errorId));
307 }
308 return Result<bool>(true);
309 }
310
311 [nodiscard]
312 public Result<WinRect> GetClientRect(void* windowHandle)
313 {
314 WinRect rect;
315 bool succeeded = WinGetClientRect(windowHandle, &rect);
316 if (!succeeded)
317 {
318 int errorId = WinAllocateWindowsError("get client rect failed", WinGetLastError());
319 return Result<WinRect>(ErrorId(errorId));
320 }
321 return Result<WinRect>(rect);
322 }
323
324 [nodiscard]
325 public Result<WinRect> GetWindowRect(void* windowHandle)
326 {
327 WinRect rect;
328 bool succeeded = WinGetWindowRect(windowHandle, &rect);
329 if (!succeeded)
330 {
331 int errorId = WinAllocateWindowsError("get window rect failed", WinGetLastError());
332 return Result<WinRect>(ErrorId(errorId));
333 }
334 return Result<WinRect>(rect);
335 }
336
337 [nodiscard]
338 public Result<Point> ClientToScreen(void* windowHandle, const Point& point)
339 {
340 Point pt(point);
341 bool succeeded = WinClientToScreen(windowHandle, &pt);
342 if (!succeeded)
343 {
344 int errorId = WinAllocateWindowsError("client to screen failed", WinGetLastError());
345 return Result<Point>(ErrorId(errorId));
346 }
347 return Result<Point>(pt);
348 }
349
350 [nodiscard]
351 public Result<Point> ScreenToClient(void* windowHandle, const Point& point)
352 {
353 Point pt(point);
354 bool succeeded = WinScreenToClient(windowHandle, &pt);
355 if (!succeeded)
356 {
357 int errorId = WinAllocateWindowsError("screen to client failed", WinGetLastError());
358 return Result<Point>(ErrorId(errorId));
359 }
360 return Result<Point>(pt);
361 }
362
363 public bool PtInRect(const Point& point, const WinRect& rect)
364 {
365 return WinPtInRect(&rect, &point);
366 }
367
368 [nodiscard]
369 public Result<bool> SetWindowText(void* windowHandle, const string& text)
370 {
371 bool succeeded = WinSetWindowText(windowHandle, text.Chars());
372 if (!succeeded)
373 {
374 int errorId = WinAllocateWindowsError("set window text failed", WinGetLastError());
375 return Result<bool>(ErrorId(errorId));
376 }
377 return Result<bool>(true);
378 }
379
380 [nodiscard]
381 public Result<int> GetWindowTextLength(void* windowHandle)
382 {
383 int result = WinGetWindowTextLength(windowHandle);
384 if (result == 0)
385 {
386 ulong errorCode = WinGetLastError();
387 if (errorCode != 0u)
388 {
389 int errorId = WinAllocateWindowsError("get window text length failed", errorCode);
390 return Result<int>(ErrorId(errorId));
391 }
392 }
393 return Result<int>(result);
394 }
395
396 [nodiscard]
397 public Result<string> GetWindowText(void* windowHandle)
398 {
399 Result<int> lengthResult = GetWindowTextLength(windowHandle);
400 if (lengthResult.Error())
401 {
402 return Result<string>(ErrorId(lengthResult.GetErrorId()));
403 }
404 int length = lengthResult.Value();
405 UniquePtr<wchar> buffer(cast<wchar*>(MemAlloc(sizeof(wchar) * (length + 1))));
406 int result = WinGetWindowText(windowHandle, buffer.Get(), length + 1);
407 if (result == 0)
408 {
409 ulong errorCode = WinGetLastError();
410 if (errorCode != 0u)
411 {
412 int errorId = WinAllocateWindowsError("get window text failed", errorCode);
413 return Result<string>(ErrorId(errorId));
414 }
415 }
416 auto utf8Result = ToUtf8(buffer.Get());
417 if (utf8Result.Error())
418 {
419 return Result<string>(ErrorId(utf8Result.GetErrorId()));
420 }
421 return Result<string>(utf8Result.Value());
422 }
423
424 [nodiscard]
425 public Result<bool> SetParentWindow(void* childWindowHandle, void* parentWindowHandle)
426 {
427 void* result = WinSetParent(childWindowHandle, parentWindowHandle);
428 if (result == null)
429 {
430 int errorId = WinAllocateWindowsError("set parent window failed", WinGetLastError());
431 return Result<bool>(ErrorId(errorId));
432 }
433 return Result<bool>(true);
434 }
435
436 [nodiscard]
437 public Result<void*> BeginPaint(void* windowHandle, void*& paintStruct)
438 {
439 void* result = WinBeginPaint(windowHandle, paintStruct);
440 if (result == null)
441 {
442 int errorId = WinAllocateWindowsError("begin paint failed", WinGetLastError());
443 return Result<void*>(ErrorId(errorId));
444 }
445 return Result<void*>(result);
446 }
447
448 public void EndPaint(void* windowHandle, void* paintStruct)
449 {
450 WinEndPaint(windowHandle, paintStruct);
451 }
452
453 [nodiscard]
454 public Result<bool> InvalidateRect(void* windowHandle, WinRect* rect, bool eraseBackground)
455 {
456 bool succeeded = WinInvalidateRect(windowHandle, rect, eraseBackground);
457 if (!succeeded)
458 {
459 int errorId = WinAllocateWindowsError("invalidate rect failed", WinGetLastError());
460 return Result<bool>(ErrorId(errorId));
461 }
462 return Result<bool>(true);
463 }
464
465 [nodiscard]
466 public Result<bool> MessageBeep(uint beepType)
467 {
468 bool succeeded = WinMessageBeep(beepType);
469 if (!succeeded)
470 {
471 int errorId = WinAllocateWindowsError("message beep failed", WinGetLastError());
472 return Result<bool>(ErrorId(errorId));
473 }
474 return Result<bool>(true);
475 }
476
477 public void* GetDC(void* windowHandle)
478 {
479 return WinGetDC(windowHandle);
480 }
481
482 [nodiscard]
483 public Result<bool> PostMessage(void* windowHandle, uint msg, ulong wparam, long lparam)
484 {
485 bool succeeded = WinPostMessage(windowHandle, msg, wparam, lparam);
486 if (!succeeded)
487 {
488 int errorId = WinAllocateWindowsError("post message failed", WinGetLastError());
489 return Result<bool>(ErrorId(errorId));
490 }
491 return Result<bool>(true);
492 }
493
494 public string CommonDialogError(uint errorCode)
495 {
496 string errorStr;
497 switch (errorCode)
498 {
499 case 65535u:
500 {
501 errorStr = "CDERR_DIALOGFAILURE";
502 break;
503 }
504 case 6u:
505 {
506 errorStr = "CDERR_FINDRESFAILURE";
507 break;
508 }
509 case 2u:
510 {
511 errorStr = "CDERR_INITIALIZATION";
512 break;
513 }
514 case 7u:
515 {
516 errorStr = "CDERR_LOADRESFAILURE";
517 break;
518 }
519 case 5u:
520 {
521 errorStr = "CDERR_LOADSTRFAILURE";
522 break;
523 }
524 case 8u:
525 {
526 errorStr = "CDERR_LOCKRESFAILURE";
527 break;
528 }
529 case 9u:
530 {
531 errorStr = "CDERR_MEMALLOCFAILURE";
532 break;
533 }
534 case 10u:
535 {
536 errorStr = "CDERR_MEMLOCKFAILURE";
537 break;
538 }
539 case 4u:
540 {
541 errorStr = "CDERR_NOHINSTANCE";
542 break;
543 }
544 case 11u:
545 {
546 errorStr = "CDERR_NOHOOK";
547 break;
548 }
549 case 3u:
550 {
551 errorStr = "CDERR_NOTEMPLATE";
552 break;
553 }
554 case 12u:
555 {
556 errorStr = "CDERR_REGISTERMSGFAIL";
557 break;
558 }
559 case 1u:
560 {
561 errorStr = "CDERR_STRUCTSIZE";
562 break;
563 }
564 case 4106u:
565 {
566 errorStr = "PDERR_CREATEICFAILURE";
567 break;
568 }
569 case 4108u:
570 {
571 errorStr = "PDERR_DEFAULTDIFFERENT";
572 break;
573 }
574 case 4105u:
575 {
576 errorStr = "PDERR_DNDMMISMATCH";
577 break;
578 }
579 case 4101u:
580 {
581 errorStr = "PDERR_GETDEVMODEFAIL";
582 break;
583 }
584 case 4102u:
585 {
586 errorStr = "PDERR_INITFAILURE";
587 break;
588 }
589 case 4100u:
590 {
591 errorStr = "PDERR_LOADDRVFAILURE";
592 break;
593 }
594 case 4104u:
595 {
596 errorStr = "PDERR_NODEFAULTPRN";
597 break;
598 }
599 case 4103u:
600 {
601 errorStr = "PDERR_NODEVICES";
602 break;
603 }
604 case 4098u:
605 {
606 errorStr = "PDERR_PARSEFAILURE";
607 break;
608 }
609 case 4107u:
610 {
611 errorStr = "PDERR_PRINTERNOTFOUND";
612 break;
613 }
614 case 4099u:
615 {
616 errorStr = "PDERR_RETDEFFAILURE";
617 break;
618 }
619 case 4097u:
620 {
621 errorStr = "PDERR_SETUPFAILURE";
622 break;
623 }
624 case 8194u:
625 {
626 errorStr = "CFERR_MAXLESSTHANMIN";
627 break;
628 }
629 case 8193u:
630 {
631 errorStr = "CFERR_NOFONTS";
632 break;
633 }
634 case 12291u:
635 {
636 errorStr = "FNERR_BUFFERTOOSMALL";
637 break;
638 }
639 case 12290u:
640 {
641 errorStr = "FNERR_INVALIDFILENAME";
642 break;
643 }
644 case 12289u:
645 {
646 errorStr = "FNERR_SUBCLASSFAILURE";
647 break;
648 }
649 case 16385u:
650 {
651 errorStr = "FRERR_BUFFERLENGTHZERO";
652 break;
653 }
654 default:
655 {
656 errorStr = "generic error";
657 break;
658 }
659 }
660 return errorStr;
661 }
662
663 public const uint OFN_READONLY = 1u;
664 public const uint OFN_OVERWRITEPROMPT = 2u;
665 public const uint OFN_HIDEREADONLY = 4u;
666 public const uint OFN_NOCHANGEDIR = 8u;
667 public const uint OFN_SHOWHELP = 16u;
668 public const uint OFN_ENABLEHOOK = 32u;
669 public const uint OFN_ENABLETEMPLATE = 64u;
670 public const uint OFN_ENABLETEMPLATEHANDLE = 128u;
671 public const uint OFN_NOVALIDATE = 256u;
672 public const uint OFN_ALLOWMULTISELECT = 512u;
673 public const uint OFN_EXTENSIONDIFFERENT = 1024u;
674 public const uint OFN_PATHMUSTEXIST = 2048u;
675 public const uint OFN_FILEMUSTEXIST = 4096u;
676 public const uint OFN_CREATEPROMPT = 8192u;
677 public const uint OFN_SHAREAWARE = 16384u;
678 public const uint OFN_NOREADONLYRETURN = 32768u;
679 public const uint OFN_NOTESTFILECREATE = 65536u;
680 public const uint OFN_NONETWORKBUTTON = 131072u;
681 public const uint OFN_NOLONGNAMES = 262144u;
682 public const uint OFN_EXPLORER = 524288u;
683 public const uint OFN_NODEREFERENCELINKS = 1048576u;
684 public const uint OFN_LONGNAMES = 2097152u;
685
686 [nodiscard]
687 public Result<bool> GetOpenFileName(void* windowHandle, const List<Pair<string, string>>& descriptionFilterPairs, const string& initialDirectory,
688 const string& defaultFilePath, const string& defaultExtension, uint flags, string& currentDirectory, List<string>& fileNames)
689 {
690 long filterBufferSize = 0;
691 for (const Pair<string, string>& descriptionFilterPair : descriptionFilterPairs)
692 {
693 auto descriptionResult = ToUtf16(descriptionFilterPair.first);
694 if (descriptionResult.Error())
695 {
696 return Result<bool>(ErrorId(descriptionResult.GetErrorId()));
697 }
698 wstring description = Rvalue(descriptionResult.Value());
699 auto filterResult = ToUtf16(descriptionFilterPair.second);
700 if (filterResult.Error())
701 {
702 return Result<bool>(ErrorId(filterResult.GetErrorId()));
703 }
704 wstring filter = Rvalue(filterResult.Value());
705 filterBufferSize = filterBufferSize + description.Length() + 1 + filter.Length() + 1;
706 }
707 filterBufferSize = filterBufferSize + 1 + 1;
708 UniquePtr<wchar> filterBuffer = cast<wchar*>(MemAlloc(sizeof(wchar) * filterBufferSize));
709 wchar* filterBufferPtr = filterBuffer.Get();
710 for (const Pair<string, string>& descriptionFilterPair : descriptionFilterPairs)
711 {
712 auto descriptionResult = ToUtf16(descriptionFilterPair.first);
713 if (descriptionResult.Error())
714 {
715 return Result<bool>(ErrorId(descriptionResult.GetErrorId()));
716 }
717 wstring description = Rvalue(descriptionResult.Value());
718 long descLen = StrCopy(filterBufferPtr, description.Chars(), description.Length());
719 filterBufferPtr = filterBufferPtr + descLen + 1;
720 auto filterResult = ToUtf16(descriptionFilterPair.second);
721 if (filterResult.Error())
722 {
723 return Result<bool>(ErrorId(filterResult.GetErrorId()));
724 }
725 wstring filter = Rvalue(filterResult.Value());
726 long filterLen = StrCopy(filterBufferPtr, filter.Chars(), filter.Length());
727 filterBufferPtr = filterBufferPtr + filterLen + 1;
728 }
729 *filterBufferPtr++ = '\0';
730 *filterBufferPtr++ = '\0';
731 long fileNameBufferSize = 16 * 1024;
732 UniquePtr<wchar> fileNameBuffer = cast<wchar*>(MemAlloc(sizeof(wchar) * fileNameBufferSize));
733 auto defaultFilePathResult = ToUtf16(defaultFilePath);
734 if (defaultFilePathResult.Error())
735 {
736 return Result<bool>(ErrorId(defaultFilePathResult.GetErrorId()));
737 }
738 wstring defFilePath = Rvalue(defaultFilePathResult.Value());
739 if (defaultFilePath.IsEmpty())
740 {
741 *fileNameBuffer.Get() = '\0';
742 }
743 else
744 {
745 StrCopy(fileNameBuffer.Get(), defFilePath.Chars(), defFilePath.Length());
746 }
747 auto initialDirResult = ToUtf16(initialDirectory);
748 if (initialDirResult.Error())
749 {
750 return Result<bool>(ErrorId(initialDirResult.GetErrorId()));
751 }
752 wstring initialDir = Rvalue(initialDirResult.Value());
753 auto defExtResult = ToUtf16(defaultExtension);
754 if (defExtResult.Error())
755 {
756 return Result<bool>(ErrorId(defExtResult.GetErrorId()));
757 }
758 wstring defExt = Rvalue(defExtResult.Value());
759 bool success = WinGetOpenFileName(windowHandle, filterBuffer.Get(), initialDir.Chars(), fileNameBuffer.Get(), cast<uint>(fileNameBufferSize), flags, defExt.Chars());
760 if (success)
761 {
762 long firstPathLength = StrLen(fileNameBuffer.Get());
763 auto firstPathResult = ToUtf8(wstring(fileNameBuffer.Get(), firstPathLength));
764 if (firstPathResult.Error())
765 {
766 return Result<bool>(ErrorId(firstPathResult.GetErrorId()));
767 }
768 string firstPath = Rvalue(firstPathResult.Value());
769 if ((flags & OFN_ALLOWMULTISELECT) == 0)
770 {
771 currentDirectory = Path.GetDirectoryName(firstPath);
772 fileNames.Add(Path.GetFileName(firstPath));
773 }
774 else
775 {
776 currentDirectory = firstPath;
777 long pathStart = firstPathLength + 1;
778 wchar* wpath = fileNameBuffer.Get() + pathStart;
779 while (*wpath != '\0')
780 {
781 long pathLength = StrLen(wpath);
782 auto pathResult = ToUtf8(wstring(wpath, pathLength));
783 if (pathResult.Error())
784 {
785 return Result<bool>(ErrorId(pathResult.GetErrorId()));
786 }
787 string path = Rvalue(pathResult.Value());
788 fileNames.Add(path);
789 wpath = wpath + pathLength + 1;
790 }
791 }
792 return Result<bool>(true);
793 }
794 else
795 {
796 uint errorCode = WinCommDlgExtendedError();
797 if (errorCode == 0u)
798 {
799 return Result<bool>(false);
800 }
801 else
802 {
803 string message = CommonDialogError(errorCode);
804 int errorId = AllocateError("get open file name failed: " + message);
805 return Result<bool>(ErrorId(errorId));
806 }
807 }
808 return Result<bool>(false);
809 }
810
811 [nodiscard]
812 public Result<bool> GetSaveFileName(void* windowHandle, const List<Pair<string, string>>& descriptionFilterPairs, const string& initialDirectory,
813 const string& defaultFilePath, const string& defaultExtension, uint flags, string& currentDirectory, string& filePath)
814 {
815 long filterBufferSize = 0;
816 for (const Pair<string, string>& descriptionFilterPair : descriptionFilterPairs)
817 {
818 auto descriptionResult = ToUtf16(descriptionFilterPair.first);
819 if (descriptionResult.Error())
820 {
821 return Result<bool>(ErrorId(descriptionResult.GetErrorId()));
822 }
823 wstring description = Rvalue(descriptionResult.Value());
824 auto filterResult = ToUtf16(descriptionFilterPair.second);
825 if (filterResult.Error())
826 {
827 return Result<bool>(ErrorId(filterResult.GetErrorId()));
828 }
829 wstring filter = Rvalue(filterResult.Value());
830 filterBufferSize = filterBufferSize + description.Length() + 1 + filter.Length() + 1;
831 }
832 filterBufferSize = filterBufferSize + 1 + 1;
833 UniquePtr<wchar> filterBuffer = cast<wchar*>(MemAlloc(sizeof(wchar) * filterBufferSize));
834 wchar* filterBufferPtr = filterBuffer.Get();
835 for (const Pair<string, string>& descriptionFilterPair : descriptionFilterPairs)
836 {
837 auto descriptionResult = ToUtf16(descriptionFilterPair.first);
838 if (descriptionResult.Error())
839 {
840 return Result<bool>(ErrorId(descriptionResult.GetErrorId()));
841 }
842 wstring description = Rvalue(descriptionResult.Value());
843 long descLen = StrCopy(filterBufferPtr, description.Chars(), description.Length());
844 filterBufferPtr = filterBufferPtr + descLen + 1;
845 auto filterResult = ToUtf16(descriptionFilterPair.second);
846 if (filterResult.Error())
847 {
848 return Result<bool>(ErrorId(filterResult.GetErrorId()));
849 }
850 wstring filter = Rvalue(filterResult.Value());
851 long filterLen = StrCopy(filterBufferPtr, filter.Chars(), filter.Length());
852 filterBufferPtr = filterBufferPtr + filterLen + 1;
853 }
854 *filterBufferPtr++ = '\0';
855 *filterBufferPtr++ = '\0';
856 long fileNameBufferSize = 1024;
857 UniquePtr<wchar> fileNameBuffer = cast<wchar*>(MemAlloc(sizeof(wchar) * fileNameBufferSize));
858 auto defFilePathResult = ToUtf16(defaultFilePath);
859 if (defFilePathResult.Error())
860 {
861 return Result<bool>(ErrorId(defFilePathResult.GetErrorId()));
862 }
863 wstring defFilePath = Rvalue(defFilePathResult.Value());
864 if (defaultFilePath.IsEmpty())
865 {
866 *fileNameBuffer.Get() = '\0';
867 }
868 else
869 {
870 StrCopy(fileNameBuffer.Get(), defFilePath.Chars(), defFilePath.Length());
871 }
872 auto initialDirResult = ToUtf16(initialDirectory);
873 if (initialDirResult.Error())
874 {
875 return Result<bool>(ErrorId(initialDirResult.GetErrorId()));
876 }
877 wstring initialDir = Rvalue(initialDirResult.Value());
878 auto defExtResult = ToUtf16(defaultExtension);
879 if (defExtResult.Error())
880 {
881 return Result<bool>(ErrorId(defExtResult.GetErrorId()));
882 }
883 wstring defExt = Rvalue(defExtResult.Value());
884 bool success = WinGetSaveFileName(windowHandle, filterBuffer.Get(), initialDir.Chars(), fileNameBuffer.Get(), cast<uint>(fileNameBufferSize), flags, defExt.Chars());
885 if (success)
886 {
887 long firstPathLength = StrLen(fileNameBuffer.Get());
888 auto filePathResult = ToUtf8(wstring(fileNameBuffer.Get(), firstPathLength));
889 if (filePathResult.Error())
890 {
891 return Result<bool>(ErrorId(filePathResult.GetErrorId()));
892 }
893 filePath = Rvalue(filePathResult.Value());
894 return Result<bool>(true);
895 }
896 else
897 {
898 uint errorCode = WinCommDlgExtendedError();
899 if (errorCode == 0u)
900 {
901 return Result<bool>(false);
902 }
903 else
904 {
905 string message = CommonDialogError(errorCode);
906 int errorId = AllocateError("get save file name failed: " + message);
907 return Result<bool>(ErrorId(errorId));
908 }
909 }
910 return Result<bool>(false);
911 }
912
913 [nodiscard]
914 public Result<void*> LoadImage(const char* name, uint type, int cx, int cy)
915 {
916 void* result = WinLoadImage(name, type, cx, cy);
917 if (result == null)
918 {
919 int errorId = WinAllocateWindowsError("load image failed", WinGetLastError());
920 return Result<void*>(ErrorId(errorId));
921 }
922 return Result<void*>(result);
923 }
924
925 [nodiscard]
926 public Result<void*> LoadCursor(const char* name)
927 {
928 void* result = WinLoadCursor(name);
929 if (result == null)
930 {
931 int errorId = WinAllocateWindowsError("load cursor failed", WinGetLastError());
932 return Result<void*>(ErrorId(errorId));
933 }
934 return Result<void*>(result);
935 }
936
937 [nodiscard]
938 public Result<void*> LoadIcon(const char* name)
939 {
940 void* result = WinLoadIcon(name);
941 if (result == null)
942 {
943 int errorId = WinAllocateWindowsError("load icon failed", WinGetLastError());
944 return Result<void*>(ErrorId(errorId));
945 }
946 return Result<void*>(result);
947 }
948
949 [nodiscard]
950 public Result<void*> LoadBitmap(const char* name)
951 {
952 void* result = WinLoadBitmap(name);
953 if (result == null)
954 {
955 int errorId = WinAllocateWindowsError("load bitmap failed", WinGetLastError());
956 return Result<void*>(ErrorId(errorId));
957 }
958 return Result<void*>(result);
959 }
960
961 [nodiscard]
962 public Result<int> GetSystemMetrics(int index)
963 {
964 int result = WinGetSystemMetrics(index);
965 if (result == 0)
966 {
967 int errorId = WinAllocateWindowsError("get system metrics failed", WinGetLastError());
968 return Result<int>(ErrorId(errorId));
969 }
970 return Result<int>(result);
971 }
972
973 public void* GetTopWindow(void* windowHandle)
974 {
975 return WinGetTopWindow(windowHandle);
976 }
977
978 [nodiscard]
979 public Result<bool> BringWindowToTop(void* windowHandle)
980 {
981 bool succeeded = WinBringWindowToTop(windowHandle);
982 if (!succeeded)
983 {
984 int errorId = WinAllocateWindowsError("bring window to top failed", WinGetLastError());
985 return Result<bool>(ErrorId(errorId));
986 }
987 return Result<bool>(true);
988 }
989
990 public enum WindowPos : int
991 {
992 top = 0, bottom = 1, topmost = -1, noTopmost = -2
993 }
994
995 public void* WindowPosHandle(WindowPos pos)
996 {
997 return cast<void*>(cast<ulong>(cast<int>(pos)));
998 }
999
1000 public enum SetWindowPosFlags : uint
1001 {
1002 SWP_ASYNCWINDOWPOS = 16384u,
1003 SWP_DEFERERASE = 8192u,
1004 SWP_DRAWFRAME = 32u,
1005 SWP_FRAMECHANGED = 32u,
1006 SWP_HIDEWINDOW = 128u,
1007 SWP_NOACTIVATE = 16u,
1008 SWP_NOCOPYBITS = 256u,
1009 SWP_NOMOVE = 2u,
1010 SWP_NOOWNERZORDER = 512u,
1011 SWP_NOREDRAW = 8u,
1012 SWP_NOREPOSITION = 512u,
1013 SWP_NOSENDCHANGING = 1024u,
1014 SWP_NOSIZE = 1u,
1015 SWP_NOZORDER = 4u,
1016 SWP_SHOWWINDOW = 64u
1017 }
1018
1019 [nodiscard]
1020 public Result<bool> SetWindowPos(void* windowHandle, void* insertAfterWindowHandle, int x, int y, int cx, int cy, SetWindowPosFlags flags)
1021 {
1022 bool succeeded = WinSetWindowPos(windowHandle, insertAfterWindowHandle, x, y, cx, cy, cast<uint>(flags));
1023 if (!succeeded)
1024 {
1025 int errorId = WinAllocateWindowsError("set window pos failed", WinGetLastError());
1026 return Result<bool>(ErrorId(errorId));
1027 }
1028 return Result<bool>(true);
1029 }
1030
1031 public enum ClassLongIndex : int
1032 {
1033 GCL_CBCLSEXTRA = -20,
1034 GCL_CBWNDEXTRA = -18,
1035 GCL_HBRBACKGROUND = -10,
1036 GCL_HCURSOR = -12,
1037 GCL_HICON = -14,
1038 GCL_HICONSM = -34,
1039 GCL_HMODULE = -16,
1040 GCL_MENUNAME = -8,
1041 GCL_STYLE = -26,
1042 GCL_WNDPROC = -24
1043 }
1044
1045 [nodiscard]
1046 public Result<long> GetClassLong(void* windowHandle, ClassLongIndex index)
1047 {
1048 long value = WinGetClassLong(windowHandle, cast<int>(index));
1049 if (value == 0)
1050 {
1051 ulong errorCode = WinGetLastError();
1052 if (errorCode != 0u)
1053 {
1054 int errorId = WinAllocateWindowsError("get class long failed", errorCode);
1055 return Result<long>(ErrorId(errorId));
1056 }
1057 }
1058 return Result<long>(value);
1059 }
1060
1061 [nodiscard]
1062 public Result<long> SetClassLong(void* windowHandle, ClassLongIndex index, long newValue)
1063 {
1064 long value = WinSetClassLong(windowHandle, cast<int>(index), newValue);
1065 if (value == 0)
1066 {
1067 ulong errorCode = WinGetLastError();
1068 if (errorCode != 0u)
1069 {
1070 int errorId = WinAllocateWindowsError("set class long failed", errorCode);
1071 return Result<long>(ErrorId(errorId));
1072 }
1073 }
1074 return Result<long>(value);
1075 }
1076
1077 public enum WindowLongIndex : int
1078 {
1079 GWL_EXSTYLE = -20,
1080 GWLP_HINSTANCE = -6,
1081 GWLP_ID = -12,
1082 GWL_STYLE = -16,
1083 GWLP_USERDATA = -21,
1084 GWLP_WNDPROC = -4
1085 }
1086
1087 [nodiscard]
1088 public Result<long> GetWindowLong(void* windowHandle, WindowLongIndex index)
1089 {
1090 long value = WinGetWindowLong(windowHandle, cast<int>(index));
1091 if (value == 0)
1092 {
1093 int errorId = WinAllocateWindowsError("get window long failed", WinGetLastError());
1094 return Result<long>(ErrorId(errorId));
1095 }
1096 return Result<long>(value);
1097 }
1098
1099 [nodiscard]
1100 public Result<bool> SetWindowLong(void* windowHandle, WindowLongIndex index, long newValue)
1101 {
1102 bool succeeded = WinSetWindowLong(windowHandle, cast<int>(index), newValue);
1103 if (!succeeded)
1104 {
1105 int errorId = WinAllocateWindowsError("set window long failed", WinGetLastError());
1106 return Result<bool>(ErrorId(errorId));
1107 }
1108 return Result<bool>(true);
1109 }
1110
1111 [nodiscard]
1112 public Result<bool> ScrollWindow(void* windowHandle, int xAmount, int yAmount, const Rect* clientRect, const Rect* clipRect)
1113 {
1114 int clientLocX = 0;
1115 int clientLocY = 0;
1116 int clientSizeW = 0;
1117 int clientSizeH = 0;
1118 if (clientRect != null)
1119 {
1120 clientLocX = clientRect->location.x;
1121 clientLocY = clientRect->location.y;
1122 clientSizeW = clientRect->size.w;
1123 clientSizeH = clientRect->size.h;
1124 }
1125 int clipLocX = 0;
1126 int clipLocY = 0;
1127 int clipSizeW = 0;
1128 int clipSizeH = 0;
1129 if (clipRect != null)
1130 {
1131 clipLocX = clipRect->location.x;
1132 clipLocY = clipRect->location.y;
1133 clipSizeW = clipRect->size.w;
1134 clipSizeH = clipRect->size.h;
1135 }
1136 bool succeeded = WinScrollWindow(windowHandle, xAmount, yAmount, clientLocX, clientLocY, clientSizeW, clientSizeH, clipLocX, clipLocY, clipSizeW, clipSizeH);
1137 if (!succeeded)
1138 {
1139 int errorId = WinAllocateWindowsError("scroll window failed", WinGetLastError());
1140 return Result<bool>(ErrorId(errorId));
1141 }
1142 return Result<bool>(true);
1143 }
1144
1145 [nodiscard]
1146 public Result<bool> ScrollWindowEx(void* windowHandle, int dx, int dy, const Rect* clientRect, const Rect* clipRect, const Rect& updateRect)
1147 {
1148 int clientLocX = 0;
1149 int clientLocY = 0;
1150 int clientSizeW = 0;
1151 int clientSizeH = 0;
1152 if (clientRect != null)
1153 {
1154 clientLocX = clientRect->location.x;
1155 clientLocY = clientRect->location.y;
1156 clientSizeW = clientRect->size.w;
1157 clientSizeH = clientRect->size.h;
1158 }
1159 int clipLocX = 0;
1160 int clipLocY = 0;
1161 int clipSizeW = 0;
1162 int clipSizeH = 0;
1163 if (clipRect != null)
1164 {
1165 clipLocX = clipRect->location.x;
1166 clipLocY = clipRect->location.y;
1167 clipSizeW = clipRect->size.w;
1168 clipSizeH = clipRect->size.h;
1169 }
1170 int x1 = updateRect.location.x;
1171 int y1 = updateRect.location.y;
1172 int x2 = updateRect.location.x + updateRect.size.w;
1173 int y2 = updateRect.location.y + updateRect.size.h;
1174 bool succeeded = WinScrollWindowEx(windowHandle, dx, dy, clientLocX, clientLocY, clientSizeW, clientSizeH, clipLocX, clipLocY, clipSizeW, clipSizeH, x1, y1, x2, y2);
1175 if (!succeeded)
1176 {
1177 int errorId = WinAllocateWindowsError("scroll window ex failed", WinGetLastError());
1178 return Result<bool>(ErrorId(errorId));
1179 }
1180 return Result<bool>(true);
1181 }
1182
1183 public enum ScrollBar : int
1184 {
1185 SB_BOTH = 3,
1186 SB_CTL = 2,
1187 SB_HORZ = 0,
1188 SB_VERT = 1
1189 }
1190
1191 [nodiscard]
1192 public Result<bool> GetScrollInfo(void* windowHandle, ScrollBar scrollBar, uint& nPage, int& nPos, int& nMin, int& nMax, int& nTrackPos)
1193 {
1194 bool succeeded = WinGetScrollInfo(windowHandle, cast<int>(scrollBar), nPage, nPos, nMin, nMax, nTrackPos);
1195 if (!succeeded)
1196 {
1197 int errorId = WinAllocateWindowsError("get scroll info failed", WinGetLastError());
1198 return Result<bool>(ErrorId(errorId));
1199 }
1200 return Result<bool>(true);
1201 }
1202
1203 public enum ScrollInfoMask : uint
1204 {
1205 SIF_DISABLENOSCROLL = 8u,
1206 SIF_PAGE = 2u,
1207 SIF_POS = 4u,
1208 SIF_RANGE = 1u
1209 }
1210
1211 public int SetScrollInfo(void* windowHandle, ScrollBar scrollBar, ScrollInfoMask mask, bool redraw, uint nPage, int nPos, int nMin, int nMax)
1212 {
1213 return WinSetScrollInfo(windowHandle, cast<int>(scrollBar), cast<uint>(mask), redraw, nPage, nPos, nMin, nMax);
1214 }
1215
1216 [nodiscard]
1217 public Result<bool> ShowScrollBar(void* windowHandle, ScrollBar scrollBar, bool show)
1218 {
1219 bool succeeded = WinShowScrollBar(windowHandle, cast<int>(scrollBar), show);
1220 if (!succeeded)
1221 {
1222 int errorId = WinAllocateWindowsError("show scroll bar failed", WinGetLastError());
1223 return Result<bool>(ErrorId(errorId));
1224 }
1225 return Result<bool>(true);
1226 }
1227
1228 [nodiscard]
1229 public Result<bool> CreateCaret(void* windowHandle, void* bitmapHandle, int width, int height)
1230 {
1231 bool succeeded = WinCreateCaret(windowHandle, bitmapHandle, width, height);
1232 if (!succeeded)
1233 {
1234 int errorId = WinAllocateWindowsError("create caret failed", WinGetLastError());
1235 return Result<bool>(ErrorId(errorId));
1236 }
1237 return Result<bool>(true);
1238 }
1239
1240 [nodiscard]
1241 public Result<bool> DestroyCaret()
1242 {
1243 bool succeeded = WinDestroyCaret();
1244 if (!succeeded)
1245 {
1246 int errorId = WinAllocateWindowsError("destroy caret failed", WinGetLastError());
1247 return Result<bool>(ErrorId(errorId));
1248 }
1249 return Result<bool>(true);
1250 }
1251
1252 [nodiscard]
1253 public Result<bool> ShowCaret(void* windowHandle)
1254 {
1255 bool succeeded = WinShowCaret(windowHandle);
1256 if (!succeeded)
1257 {
1258 int errorId = WinAllocateWindowsError("show caret failed", WinGetLastError());
1259 return Result<bool>(ErrorId(errorId));
1260 }
1261 return Result<bool>(true);
1262 }
1263
1264 [nodiscard]
1265 public Result<bool> HideCaret(void* windowHandle)
1266 {
1267 bool succeeded = WinHideCaret(windowHandle);
1268 if (!succeeded)
1269 {
1270 int errorId = WinAllocateWindowsError("hide caret failed", WinGetLastError());
1271 return Result<bool>(ErrorId(errorId));
1272 }
1273 return Result<bool>(true);
1274 }
1275
1276 [nodiscard]
1277 public Result<Point> GetCaretPos()
1278 {
1279 Point caretPos;
1280 bool succeeded = WinGetCaretPos(caretPos.x, caretPos.y);
1281 if (!succeeded)
1282 {
1283 int errorId = WinAllocateWindowsError("get caret pos failed", WinGetLastError());
1284 return Result<Point>(ErrorId(errorId));
1285 }
1286 return Result<Point>(caretPos);
1287 }
1288
1289 [nodiscard]
1290 public Result<bool> SetCaretPos(const Point& caretPos)
1291 {
1292 bool succeeded = WinSetCaretPos(caretPos.x, caretPos.y);
1293 if (!succeeded)
1294 {
1295 int errorId = WinAllocateWindowsError("set caret pos failed", WinGetLastError());
1296 return Result<bool>(ErrorId(errorId));
1297 }
1298 return Result<bool>(true);
1299 }
1300
1301 [nodiscard]
1302 public Result<bool> SetTimer(void* windowHandle, uint timerId, uint elapseMs)
1303 {
1304 bool succeeded = WinSetTimer(windowHandle, timerId, elapseMs);
1305 if (!succeeded)
1306 {
1307 int errorId = WinAllocateWindowsError("set timer failed", WinGetLastError());
1308 return Result<bool>(ErrorId(errorId));
1309 }
1310 return Result<bool>(true);
1311 }
1312
1313 [nodiscard]
1314 public Result<bool> KillTimer(void* windowHandle, uint timerId)
1315 {
1316 bool succeeded = WinKillTimer(windowHandle, timerId);
1317 if (!succeeded)
1318 {
1319 int errorId = WinAllocateWindowsError("kill timer failed", WinGetLastError());
1320 return Result<bool>(ErrorId(errorId));
1321 }
1322 return Result<bool>(true);
1323 }
1324
1325 [nodiscard]
1326 public Result<uint> RegisterClipboardFormat(const char* formatName)
1327 {
1328 uint format = WinRegisterClipboardFormat(formatName);
1329 if (format == 0u)
1330 {
1331 int errorId = WinAllocateWindowsError("register clipboard format failed", WinGetLastError());
1332 return Result<uint>(ErrorId(errorId));
1333 }
1334 return Result<uint>(format);
1335 }
1336
1337 [nodiscard]
1338 public Result<bool> OpenClipboard(void* windowHandle)
1339 {
1340 uint maxWait = 100u;
1341 for (int i = 0; i < 5; ++i;)
1342 {
1343 bool succeeded = WinOpenClipboard(windowHandle);
1344 if (succeeded)
1345 {
1346 return Result<bool>(true);
1347 }
1348 else if (i < 4)
1349 {
1350 Sleep(Duration.FromMilliseconds(Random() % maxWait));
1351 maxWait = maxWait * 2u;
1352 }
1353 }
1354 int errorId = WinAllocateWindowsError("open clipboard failed", WinGetLastError());
1355 return Result<bool>(ErrorId(errorId));
1356 }
1357
1358 [nodiscard]
1359 public Result<bool> CloseClipboard()
1360 {
1361 bool succeeded = WinCloseClipboard();
1362 if (!succeeded)
1363 {
1364 int errorId = WinAllocateWindowsError("close clipboard failed", WinGetLastError());
1365 return Result<bool>(ErrorId(errorId));
1366 }
1367 return Result<bool>(true);
1368 }
1369
1370 [nodiscard]
1371 public Result<bool> EmptyClipboard()
1372 {
1373 bool succeeded = WinEmptyClipboard();
1374 if (!succeeded)
1375 {
1376 int errorId = WinAllocateWindowsError("empty clipboard failed", WinGetLastError());
1377 return Result<bool>(ErrorId(errorId));
1378 }
1379 return Result<bool>(true);
1380 }
1381
1382 [nodiscard]
1383 public Result<void*> SetClipboardData(uint format, void* mem)
1384 {
1385 void* retval = WinSetClipboardData(format, mem);
1386 if (retval == null)
1387 {
1388 int errorId = WinAllocateWindowsError("set clipboard data failed", WinGetLastError());
1389 return Result<void*>(ErrorId(errorId));
1390 }
1391 return Result<void*>(retval);
1392 }
1393
1394 [nodiscard]
1395 public Result<void*> GetClipboardData(uint format)
1396 {
1397 void* retval = WinGetClipboardData(format);
1398 if (retval == null)
1399 {
1400 int errorId = WinAllocateWindowsError("get clipboard data failed", WinGetLastError());
1401 return Result<void*>(ErrorId(errorId));
1402 }
1403 return Result<void*>(retval);
1404 }
1405
1406 public bool IsClipboardFormatAvailable(uint format)
1407 {
1408 return WinIsClipboardFormatAvailable(format);
1409 }
1410
1411 [nodiscard]
1412 public Result<bool> AddClipboardFormatListener(void* windowHandle)
1413 {
1414 bool succeeded = WinAddClipboardFormatListener(windowHandle);
1415 if (!succeeded)
1416 {
1417 int errorId = WinAllocateWindowsError("add clipboard format listener failed", WinGetLastError());
1418 return Result<bool>(ErrorId(errorId));
1419 }
1420 return Result<bool>(true);
1421 }
1422
1423 [nodiscard]
1424 public Result<bool> RemoveClipboardFormatListener(void* windowHandle)
1425 {
1426 bool succeeded = WinRemoveClipboardFormatListener(windowHandle);
1427 if (!succeeded)
1428 {
1429 int errorId = WinAllocateWindowsError("remove clipboard format listener failed", WinGetLastError());
1430 return Result<bool>(ErrorId(errorId));
1431 }
1432 return Result<bool>(true);
1433 }
1434
1435 public enum GlobalAllocFlags : uint
1436 {
1437 GMEM_FIXED = 0u,
1438 GHND = 66u,
1439 GMEM_MOVEABLE = 2u,
1440 GMEM_ZEROINIT = 64u,
1441 GPTR = 64u
1442 }
1443
1444 [nodiscard]
1445 public Result<void*> GlobalAlloc(GlobalAllocFlags flags, ulong size)
1446 {
1447 void* retval = WinGlobalAlloc(cast<uint>(flags), size);
1448 if (retval == null)
1449 {
1450 int errorId = WinAllocateWindowsError("global alloc failed", WinGetLastError());
1451 return Result<void*>(ErrorId(errorId));
1452 }
1453 return Result<void*>(retval);
1454 }
1455
1456 [nodiscard]
1457 public Result<void*> GlobalLock(void* memHandle)
1458 {
1459 void* retval = WinGlobalLock(memHandle);
1460 if (retval == null)
1461 {
1462 int errorId = WinAllocateWindowsError("global lock failed", WinGetLastError());
1463 return Result<void*>(ErrorId(errorId));
1464 }
1465 return Result<void*>(retval);
1466 }
1467
1468 [nodiscard]
1469 public Result<bool> GlobalUnlock(void* memHandle)
1470 {
1471 bool retval = WinGlobalUnlock(memHandle);
1472 if (!retval)
1473 {
1474 ulong error = WinGetLastError();
1475 if (error != 0u)
1476 {
1477 int errorId = WinAllocateWindowsError("global unlock failed", error);
1478 return Result<bool>(ErrorId(errorId));
1479 }
1480 }
1481 return Result<bool>(true);
1482 }
1483
1484 [nodiscard]
1485 public Result<bool> GlobalFree(void* memHandle)
1486 {
1487 void* retval = WinGlobalFree(memHandle);
1488 if (retval != null)
1489 {
1490 int errorId = WinAllocateWindowsError("global free failed", WinGetLastError());
1491 return Result<bool>(ErrorId(errorId));
1492 }
1493 return Result<bool>(true);
1494 }
1495
1496 [nodiscard]
1497 public Result<ulong> GlobalSize(void* memHandle)
1498 {
1499 ulong size = WinGlobalSize(memHandle);
1500 if (size == 0u)
1501 {
1502 int errorId = WinAllocateWindowsError("global size failed", WinGetLastError());
1503 return Result<ulong>(ErrorId(errorId));
1504 }
1505 return Result<ulong>(size);
1506 }
1507
1508 [nodiscard]
1509 public Result<bool> GetCursorPos(int& x, int& y)
1510 {
1511 if (!WinGetCursorPos(x, y))
1512 {
1513 int errorId = WinAllocateWindowsError("get cursor pos failed", WinGetLastError());
1514 return Result<bool>(ErrorId(errorId));
1515 }
1516 return Result<bool>(true);
1517 }
1518
1519 [nodiscard]
1520 public Result<string> GetFolder(void* windowHandle, const string& defaultDirectory)
1521 {
1522 auto defaultDirResult = ToUtf16(defaultDirectory);
1523 if (defaultDirResult.Error())
1524 {
1525 return Result<string>(ErrorId(defaultDirResult.GetErrorId()));
1526 }
1527 wstring defaultDir = Rvalue(defaultDirResult.Value());
1528 long folderNameBufferSize = 1024;
1529 UniquePtr<wchar> folderNameBuffer = cast<wchar*>(MemAlloc(sizeof(wchar) * folderNameBufferSize));
1530 bool success = WinGetFolder(windowHandle, defaultDir.Chars(), folderNameBuffer.Get(), cast<uint>(folderNameBufferSize));
1531 if (success)
1532 {
1533 wstring folderName(folderNameBuffer.Get());
1534 auto utf8Result = ToUtf8(folderName);
1535 if (utf8Result.Error())
1536 {
1537 return utf8Result;
1538 }
1539 else
1540 {
1541 return Result<string>(utf8Result.Value());
1542 }
1543 }
1544 else
1545 {
1546 int errorId = AllocateError("GetFolder failed");
1547 return Result<string>(ErrorId(errorId));
1548 }
1549 }