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     }