1 /* 2 Copyright (C) 2004-2007 Christopher E. Miller 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely, subject to the following restrictions: 11 12 1. The origin of this software must not be misrepresented; you must not 13 claim that you wrote the original software. If you use this software 14 in a product, an acknowledgment in the product documentation would be 15 appreciated but is not required. 16 2. Altered source versions must be plainly marked as such, and must not be 17 misrepresented as being the original software. 18 3. This notice may not be removed or altered from any source distribution. 19 */ 20 21 module dfl.internal.utf; 22 23 import core.sys.windows.windows; 24 import core.sys.windows.richedit; 25 26 import dfl.internal.dlib; 27 import dfl.internal.clib; 28 29 // FIX: import dfl.internal.winapi; 30 31 import std.windows.charset; 32 33 version (DFL_NO_D2_AND_ABOVE) { 34 } else { 35 version (D_Version2) { 36 version = DFL_D2_AND_ABOVE; 37 } else version (D_Version3) { 38 version = DFL_D3_AND_ABOVE; 39 version = DFL_D2_AND_ABOVE; 40 } 41 } 42 43 // Do not support Win9x. 44 version = DFL_UNICODE; 45 enum useUnicode = true; 46 47 package: 48 49 version (DFL_LOAD_INTERNAL_LIBS) { 50 alias initInternalLib = LoadLibraryA; 51 } else { 52 version = DFL_GET_INTERNAL_LIBS; 53 54 alias initInternalLib = GetModuleHandleA; 55 } 56 57 HMODULE _user32, _kernel32, _advapi32, _gdi32; 58 59 package @property HMODULE advapi32() nothrow { // getter 60 // advapi32 generally always delay loads. 61 if (!_advapi32) { 62 _advapi32 = LoadLibraryA("advapi32.dll"); 63 } 64 return _advapi32; 65 } 66 67 package @property HMODULE gdi32() nothrow { // getter 68 // gdi32 sometimes delay loads. 69 version (DFL_GET_INTERNAL_LIBS) { 70 if (!_gdi32) { 71 _gdi32 = LoadLibraryA("gdi32.dll"); 72 } 73 } 74 return _gdi32; 75 } 76 77 package @property HMODULE user32() nothrow { // getter 78 version (DFL_GET_INTERNAL_LIBS) { 79 if (!_user32) { 80 _user32 = LoadLibraryA("user32.dll"); 81 } 82 } 83 return _user32; 84 } 85 86 package @property HMODULE kernel32() nothrow { // getter 87 version (DFL_GET_INTERNAL_LIBS) { 88 if (!_kernel32) { 89 _kernel32 = LoadLibraryA("kernel32.dll"); 90 } 91 } 92 return _kernel32; 93 } 94 95 private: 96 97 version (DFL_UNICODE) version = STATIC_UNICODE; 98 99 public void _utfinit() { // package 100 version (DFL_UNICODE) { 101 } else version (DFL_ANSI) { 102 } else { 103 /+ 104 OSVERSIONINFOA osv; 105 osv.dwOSVersionInfoSize = OSVERSIONINFOA.sizeof; 106 if(GetVersionExA(&osv)) { 107 useUnicode = osv.dwPlatformId == VER_PLATFORM_WIN32_NT; 108 } 109 +/ 110 111 _user32 = initInternalLib("user32.dll"); 112 _kernel32 = initInternalLib("kernel32.dll"); 113 _advapi32 = GetModuleHandleA("advapi32.dll"); // Not guaranteed to be loaded. 114 _gdi32 = initInternalLib("gdi32.dll"); 115 } 116 } 117 118 template _getlen(T) { 119 size_t _getlen(T* tz) 120 in { 121 assert(tz); 122 } 123 body { 124 T* p; 125 for (p = tz; *p; p++) { 126 } 127 return p - tz; 128 } 129 } 130 131 public: 132 133 Dstringz unsafeStringz(Dstring s) nothrow { 134 if (!s.length) { 135 return ""; 136 } 137 138 // Check if already null terminated. 139 if (!s.ptr[s.length]) { // Disables bounds checking. 140 return s.ptr; 141 } 142 143 // Need to duplicate with null terminator. 144 char[] result; 145 result = new char[s.length + 1]; 146 result[0 .. s.length] = s[]; 147 result[s.length] = 0; 148 //return result.ptr; 149 return cast(Dstringz) result.ptr; // Needed in D2. 150 } 151 152 Dstring unicodeToAnsi(Dwstringz unicode, size_t ulen) { 153 if (!ulen) { 154 return null; 155 } 156 157 wchar* wsz; 158 char[] result; 159 int len; 160 161 len = WideCharToMultiByte(0, 0, unicode, ulen, null, 0, null, null); 162 assert(len > 0); 163 164 result = new char[len]; 165 len = WideCharToMultiByte(0, 0, unicode, ulen, result.ptr, len, null, null); 166 assert(len == result.length); 167 //return result[0 .. len - 1]; 168 return cast(Dstring) result[0 .. len - 1]; // Needed in D2. 169 } 170 171 Dwstring ansiToUnicode(Dstringz ansi, size_t len) { 172 wchar[] ws; 173 174 len++; 175 ws = new wchar[len]; 176 177 len = MultiByteToWideChar(0, 0, ansi, len, ws.ptr, len); 178 //assert(len == ws.length); 179 ws = ws[0 .. len - 1]; // Exclude null char at end. 180 181 //return ws; 182 return cast(Dwstring) ws; // Needed in D2. 183 } 184 185 Dstring fromAnsi(Dstringz ansi, size_t len) { 186 return utf16stringtoUtf8string(ansiToUnicode(ansi, len)); 187 } 188 189 version (DFL_D2_AND_ABOVE) { 190 Dstring fromAnsi(char* ansi, size_t len) { 191 return fromAnsi(cast(Dstringz) ansi, len); 192 } 193 } 194 195 Dstring fromAnsiz(Dstringz ansiz) { 196 if (!ansiz) { 197 return null; 198 } 199 200 //return fromAnsi(ansiz, _getlen!(char)(ansiz)); 201 return fromAnsi(ansiz, _getlen(ansiz)); 202 } 203 204 version (DFL_D2_AND_ABOVE) { 205 Dstring fromAnsiz(char* ansi) { 206 return fromAnsiz(cast(Dstringz) ansi); 207 } 208 } 209 210 private Dstring _toAnsiz(Dstring utf8, bool safe = true) { 211 // This function is intentionally unsafe; depends on "safe" param. 212 foreach (char ch; utf8) { 213 if (ch >= 0x80) { 214 char[] result; 215 auto wsz = utf8stringToUtf16stringz(utf8); 216 auto len = WideCharToMultiByte(0, 0, wsz, -1, null, 0, null, null); 217 assert(len > 0); 218 219 result = new char[len]; 220 len = WideCharToMultiByte(0, 0, wsz, -1, result.ptr, len, null, null); 221 assert(len == result.length); 222 //return result[0 .. len - 1]; 223 return cast(Dstring) result[0 .. len - 1]; // Needed in D2. 224 } 225 } 226 227 // Don't need conversion. 228 if (safe) //return stringToStringz(utf8)[0 .. utf8.length]; 229 { 230 return cast(Dstring) stringToStringz(utf8)[0 .. utf8.length]; // Needed in D2. 231 } 232 return unsafeStringz(utf8)[0 .. utf8.length]; 233 } 234 235 private size_t toAnsiLength(Dstring utf8) { 236 foreach (char ch; utf8) { 237 if (ch >= 0x80) { 238 auto wsz = utf8stringToUtf16stringz(utf8); 239 auto len = WideCharToMultiByte(0, 0, wsz, -1, null, 0, null, null); 240 assert(len > 0); 241 return len - 1; // Minus null. 242 } 243 } 244 return utf8.length; // Just ASCII; same length. 245 } 246 247 private Dstring _unsafeAnsiz(Dstring utf8) { 248 return _toAnsiz(utf8, false); 249 } 250 251 Dstringz toAnsiz(Dstring utf8, bool safe = true) { 252 return _toAnsiz(utf8, safe).ptr; 253 } 254 255 Dstringz unsafeAnsiz(Dstring utf8) { 256 return _toAnsiz(utf8, false).ptr; 257 } 258 259 Dstring toAnsi(Dstring utf8, bool safe = true) { 260 return _toAnsiz(utf8, safe); 261 } 262 263 Dstring unsafeAnsi(Dstring utf8) { 264 return _toAnsiz(utf8, false); 265 } 266 267 Dstring fromUnicode(Dwstringz unicode, size_t len) { 268 return utf16stringtoUtf8string(unicode[0 .. len]); 269 } 270 271 version (DFL_D2_AND_ABOVE) { 272 Dstring fromUnicode(wchar* unicode, size_t len) { 273 return fromUnicode(cast(Dwstringz) unicode, len); 274 } 275 } 276 277 Dstring fromUnicodez(Dwstringz unicodez) { 278 if (!unicodez) { 279 return null; 280 } 281 282 //return fromUnicode(unicodez, _getlen!(wchar)(unicodez)); 283 return fromUnicode(unicodez, _getlen(unicodez)); 284 } 285 286 version (DFL_D2_AND_ABOVE) { 287 Dstring fromUnicodez(wchar* unicodez) { 288 return fromUnicodez(cast(Dwstringz) unicodez); 289 } 290 } 291 292 Dwstringz toUnicodez(Dstring utf8) { 293 //return utf8stringToUtf16stringz(utf8); 294 return cast(Dwstringz) utf8stringToUtf16stringz(utf8); // Needed in D2. 295 } 296 297 Dwstring toUnicode(Dstring utf8) { 298 return utf8stringtoUtf16string(utf8); 299 } 300 301 size_t toUnicodeLength(Dstring utf8) { 302 size_t result = 0; 303 foreach (wchar wch; utf8) { 304 result++; 305 } 306 return result; 307 } 308 309 extern (Windows) { 310 alias CreateWindowExWProc = HWND function(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, 311 DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, 312 HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam); 313 alias GetWindowTextLengthWProc = int function(HWND hWnd); 314 alias GetWindowTextWProc = int function(HWND hWnd, LPCWSTR lpString, int nMaxCount); 315 alias SetWindowTextWProc = BOOL function(HWND hWnd, LPCWSTR lpString); 316 alias SendMessageWProc = LRESULT function(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 317 alias CallWindowProcWProc = LRESULT function(WNDPROC lpPrevWndFunc, HWND hWnd, 318 UINT Msg, WPARAM wParam, LPARAM lParam); 319 alias RegisterClipboardFormatWProc = UINT function(LPCWSTR lpszFormat); 320 alias GetClipboardFormatNameWProc = int function(UINT format, 321 LPWSTR lpszFormatName, int cchMaxCount); 322 alias DrawTextExWProc = int function(HDC hdc, LPWSTR lpchText, int cchText, 323 LPRECT lprc, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams); 324 alias SetCurrentDirectoryWProc = BOOL function(LPCWSTR lpPathName); 325 alias GetCurrentDirectoryWProc = DWORD function(DWORD nBufferLength, LPWSTR lpBuffer); 326 alias GetComputerNameWProc = BOOL function(LPWSTR lpBuffer, LPDWORD nSize); 327 alias GetSystemDirectoryWProc = UINT function(LPWSTR lpBuffer, UINT uSize); 328 alias GetUserNameWProc = BOOL function(LPWSTR lpBuffer, LPDWORD nSize); 329 alias ExpandEnvironmentStringsWProc = DWORD function(LPCWSTR lpSrc, LPWSTR lpDst, DWORD nSize); 330 alias GetEnvironmentVariableWProc = DWORD function(LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize); 331 alias RegSetValueExWProc = LONG function(HKEY hKey, LPCWSTR lpValueName, 332 DWORD Reserved, DWORD dwType, BYTE* lpData, DWORD cbData); 333 alias RegCreateKeyExWProc = LONG function(HKEY hKey, LPCWSTR lpSubKey, 334 DWORD Reserved, LPWSTR lpClass, DWORD dwOptions, REGSAM samDesired, 335 LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition); 336 alias RegOpenKeyExWProc = LONG function(HKEY hKey, LPCWSTR lpSubKey, 337 DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); 338 alias RegDeleteKeyWProc = LONG function(HKEY hKey, LPCWSTR lpSubKey); 339 alias RegEnumKeyExWProc = LONG function(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcbName, 340 LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcbClass, PFILETIME lpftLastWriteTime); 341 alias RegQueryValueExWProc = LONG function(HKEY hKey, LPCWSTR lpValueName, 342 LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); 343 alias RegEnumValueWProc = LONG function(HKEY hKey, DWORD dwIndex, LPTSTR lpValueName, 344 LPDWORD lpcbValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); 345 alias RegisterClassWProc = ATOM function(WNDCLASSW* lpWndClass); 346 alias GetTextExtentPoint32WProc = BOOL function(HDC hdc, LPCWSTR lpString, 347 int cbString, LPSIZE lpSize); 348 alias LoadImageWProc = HANDLE function(HINSTANCE hinst, LPCWSTR lpszName, 349 UINT uType, int cxDesired, int cyDesired, UINT fuLoad); 350 alias DragQueryFileWProc = UINT function(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch); 351 alias GetModuleFileNameWProc = DWORD function(HMODULE hModule, LPWSTR lpFilename, DWORD nSize); 352 alias DispatchMessageWProc = LONG function(MSG* lpmsg); 353 alias PeekMessageWProc = BOOL function(LPMSG lpMsg, HWND hWnd, 354 UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); 355 alias IsDialogMessageWProc = BOOL function(HWND hDlg, LPMSG lpMsg); 356 alias DefWindowProcWProc = LRESULT function(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); 357 alias DefDlgProcWProc = LRESULT function(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam); 358 alias DefFrameProcWProc = LRESULT function(HWND hWnd, HWND hWndMDIClient, 359 UINT uMsg, WPARAM wParam, LPARAM lParam); 360 alias DefMDIChildProcWProc = LRESULT function(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 361 alias GetClassInfoWProc = BOOL function(HINSTANCE hInstance, 362 LPCWSTR lpClassName, LPWNDCLASSW lpWndClass); 363 alias FindFirstChangeNotificationWProc = HANDLE function(LPCWSTR lpPathName, 364 BOOL bWatchSubtree, DWORD dwNotifyFilter); 365 alias GetFullPathNameWProc = DWORD function(LPCWSTR lpFileName, 366 DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart); 367 alias LoadLibraryExWProc = typeof(&LoadLibraryExW); 368 alias SetMenuItemInfoWProc = typeof(&SetMenuItemInfoW); 369 alias InsertMenuItemWProc = typeof(&InsertMenuItemW); 370 alias CreateFontIndirectWProc = typeof(&CreateFontIndirectW); 371 alias GetObjectWProc = typeof(&GetObjectW); 372 } 373 374 private void getProcErr(Dstring procName) { 375 Dstring errdesc; 376 version (DFL_NO_PROC_ERROR_INFO) { 377 } else { 378 auto le = cast(int) GetLastError(); 379 if (le) { 380 errdesc = " (error " ~ intToString(le) ~ ")"; 381 } 382 } 383 throw new Exception("Unable to load procedure " ~ procName ~ errdesc); 384 } 385 386 // If loading from a resource just use LoadImageA(). 387 HANDLE loadImage(HINSTANCE hinst, Dstring name, UINT uType, int cxDesired, int cyDesired, UINT fuLoa) { 388 if (useUnicode) { 389 version (STATIC_UNICODE) { 390 alias proc = LoadImageW; 391 } else { 392 enum NAME = "LoadImageW"; 393 static LoadImageWProc proc = null; 394 395 if (!proc) { 396 proc = cast(LoadImageWProc) GetProcAddress(user32, NAME.ptr); 397 if (!proc) { 398 getProcErr(NAME); 399 } 400 } 401 } 402 403 return proc(hinst, toUnicodez(name), uType, cxDesired, cyDesired, fuLoa); 404 } else { 405 return LoadImageA(hinst, unsafeAnsiz(name), uType, cxDesired, cyDesired, fuLoa); 406 } 407 } 408 409 HWND createWindowEx(DWORD dwExStyle, Dstring className, Dstring windowName, DWORD dwStyle, 410 int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, 411 HINSTANCE hInstance, LPVOID lpParam) { 412 if (useUnicode) { 413 version (STATIC_UNICODE) { 414 alias proc = CreateWindowExW; 415 } else { 416 enum NAME = "CreateWindowExW"; 417 static CreateWindowExWProc proc = null; 418 419 if (!proc) { 420 proc = cast(CreateWindowExWProc) GetProcAddress(user32, NAME.ptr); 421 if (!proc) { 422 getProcErr(NAME); 423 } 424 } 425 } 426 427 //if(windowName.length) 428 // MessageBoxW(null, toUnicodez(windowName), toUnicodez(className ~ " caption"), 0); 429 return proc(dwExStyle, toUnicodez(className), toUnicodez(windowName), 430 dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); 431 } else { 432 return CreateWindowExA(dwExStyle, unsafeAnsiz(className), unsafeAnsiz(windowName), 433 dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); 434 } 435 } 436 437 HWND createWindow(Dstring className, Dstring windowName, DWORD dwStyle, int x, int y, 438 int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HANDLE hInstance, LPVOID lpParam) { 439 return createWindowEx(0, className, windowName, dwStyle, x, y, nWidth, 440 nHeight, hWndParent, hMenu, hInstance, lpParam); 441 } 442 443 Dstring getWindowText(HWND hwnd) { 444 if (useUnicode) { 445 version (STATIC_UNICODE) { 446 alias proc = GetWindowTextW; 447 alias proclen = GetWindowTextLengthW; 448 } else { 449 enum NAME = "GetWindowTextW"; 450 static GetWindowTextWProc proc = null; 451 452 enum NAMELEN = "GetWindowTextLengthW"; 453 static GetWindowTextLengthWProc proclen = null; 454 455 if (!proc) { 456 proc = cast(GetWindowTextWProc) GetProcAddress(user32, NAME.ptr); 457 if (!proc) { 458 getProcErr(NAME); 459 } 460 461 //if(!proclen) 462 { 463 proclen = cast(GetWindowTextLengthWProc) GetProcAddress(user32, NAMELEN.ptr); 464 //if(!proclen) 465 // getProcErr(NAMELEN); 466 } 467 } 468 } 469 470 wchar* buf; 471 size_t len; 472 473 len = proclen(hwnd); 474 if (!len) { 475 return null; 476 } 477 len++; 478 buf = (new wchar[len]).ptr; 479 480 len = proc(hwnd, buf, len); 481 return fromUnicode(buf, len); 482 } else { 483 char* buf; 484 size_t len; 485 486 len = GetWindowTextLengthA(hwnd); 487 if (!len) { 488 return null; 489 } 490 len++; 491 buf = (new char[len]).ptr; 492 493 len = GetWindowTextA(hwnd, buf, len); 494 return fromAnsi(buf, len); 495 } 496 } 497 498 BOOL setWindowText(HWND hwnd, Dstring str) { 499 if (useUnicode) { 500 version (STATIC_UNICODE) { 501 alias proc = SetWindowTextW; 502 } else { 503 enum NAME = "SetWindowTextW"; 504 static SetWindowTextWProc proc = null; 505 506 if (!proc) { 507 proc = cast(SetWindowTextWProc) GetProcAddress(user32, NAME.ptr); 508 if (!proc) { 509 getProcErr(NAME); 510 } 511 } 512 } 513 514 return proc(hwnd, toUnicodez(str)); 515 } else { 516 return SetWindowTextA(hwnd, unsafeAnsiz(str)); 517 } 518 } 519 520 Dstring getModuleFileName(HMODULE hmod) { 521 if (useUnicode) { 522 version (STATIC_UNICODE) { 523 alias proc = GetModuleFileNameW; 524 } else { 525 enum NAME = "GetModuleFileNameW"; 526 static GetModuleFileNameWProc proc = null; 527 528 if (!proc) { 529 proc = cast(GetModuleFileNameWProc) GetProcAddress(kernel32, NAME.ptr); 530 if (!proc) { 531 getProcErr(NAME); 532 } 533 } 534 } 535 536 wchar[] s; 537 DWORD len; 538 s = new wchar[MAX_PATH]; 539 len = proc(hmod, s.ptr, s.length); 540 return fromUnicode(s.ptr, len); 541 } else { 542 char[] s; 543 DWORD len; 544 s = new char[MAX_PATH]; 545 len = GetModuleFileNameA(hmod, s.ptr, s.length); 546 return fromAnsi(s.ptr, len); 547 } 548 } 549 550 version = STATIC_UNICODE_SEND_MESSAGE; 551 552 version (STATIC_UNICODE_SEND_MESSAGE) { 553 } else { 554 version (DFL_UNICODE) { 555 version = STATIC_UNICODE_SEND_MESSAGE; 556 } else version (DFL_ANSI) { 557 } else { 558 private SendMessageWProc _loadSendMessageW() { 559 enum NAME = "SendMessageW"; 560 static SendMessageWProc proc = null; 561 562 if (!proc) { 563 proc = cast(SendMessageWProc) GetProcAddress(user32, NAME.ptr); 564 if (!proc) { 565 getProcErr(NAME); 566 } 567 } 568 569 return proc; 570 } 571 } 572 } 573 574 // Sends EM_GETSELTEXT to a rich text box and returns the text. 575 Dstring emGetSelText(HWND hwnd, size_t selTextLength) { 576 if (useUnicode) { 577 version (STATIC_UNICODE_SEND_MESSAGE) { 578 alias proc = SendMessageW; 579 } else { 580 SendMessageWProc proc; 581 proc = _loadSendMessageW(); 582 } 583 584 wchar[] buf; 585 size_t len; 586 buf = new wchar[selTextLength + 1]; 587 len = proc(hwnd, EM_GETSELTEXT, 0, cast(LPARAM) buf.ptr); 588 return fromUnicode(buf.ptr, len); 589 } else { 590 char[] buf; 591 size_t len; 592 buf = new char[selTextLength + 1]; 593 len = SendMessageA(hwnd, EM_GETSELTEXT, 0, cast(LPARAM) buf.ptr); 594 return fromAnsi(buf.ptr, len); 595 } 596 } 597 598 // Gets the selected text of an edit box. 599 // This needs to retrieve the entire text and strip out the extra. 600 Dstring getSelectedText(HWND hwnd) { 601 uint v1, v2; 602 uint len; 603 604 if (useUnicode) { 605 version (STATIC_UNICODE_SEND_MESSAGE) { 606 alias proc = SendMessageW; 607 } else { 608 SendMessageWProc proc; 609 proc = _loadSendMessageW(); 610 } 611 612 proc(hwnd, EM_GETSEL, cast(WPARAM)&v1, cast(LPARAM)&v2); 613 if (v1 == v2) { 614 return null; 615 } 616 assert(v2 > v1); 617 618 len = proc(hwnd, WM_GETTEXTLENGTH, 0, 0); 619 if (len) { 620 len++; 621 wchar* buf; 622 buf = (new wchar[len]).ptr; 623 624 len = proc(hwnd, WM_GETTEXT, len, cast(LPARAM) buf); 625 if (len) { 626 wchar[] s; 627 s = buf[v1 .. v2].dup; 628 return fromUnicode(s.ptr, s.length); 629 } 630 } 631 } else { 632 SendMessageA(hwnd, EM_GETSEL, cast(WPARAM)&v1, cast(LPARAM)&v2); 633 if (v1 == v2) { 634 return null; 635 } 636 assert(v2 > v1); 637 638 len = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0); 639 if (len) { 640 len++; 641 char* buf; 642 buf = (new char[len]).ptr; 643 644 len = SendMessageA(hwnd, WM_GETTEXT, len, cast(LPARAM) buf); 645 if (len) { 646 char[] s; 647 s = buf[v1 .. v2].dup; 648 return fromAnsi(s.ptr, s.length); 649 } 650 } 651 } 652 653 return null; 654 } 655 656 // Sends EM_SETPASSWORDCHAR to an edit box. 657 // TODO: check if correct implementation. 658 void emSetPasswordChar(HWND hwnd, dchar pwc) { 659 if (useUnicode) { 660 version (STATIC_UNICODE_SEND_MESSAGE) { 661 alias proc = SendMessageW; 662 } else { 663 SendMessageWProc proc; 664 proc = _loadSendMessageW(); 665 } 666 667 proc(hwnd, EM_SETPASSWORDCHAR, pwc, 0); // ? 668 } else { 669 Dstring chs; 670 Dstring ansichs; 671 chs = utf32stringtoUtf8string((&pwc)[0 .. 1]); 672 ansichs = unsafeAnsi(chs); 673 674 if (ansichs) { 675 SendMessageA(hwnd, EM_SETPASSWORDCHAR, ansichs[0], 0); // ? 676 } 677 } 678 } 679 680 // Sends EM_GETPASSWORDCHAR to an edit box. 681 // TODO: check if correct implementation. 682 dchar emGetPasswordChar(HWND hwnd) { 683 if (useUnicode) { 684 version (STATIC_UNICODE_SEND_MESSAGE) { 685 alias proc = SendMessageW; 686 } else { 687 SendMessageWProc proc; 688 proc = _loadSendMessageW(); 689 } 690 691 return cast(dchar) proc(hwnd, EM_GETPASSWORDCHAR, 0, 0); // ? 692 } else { 693 char ansich; 694 Dstring chs; 695 Ddstring dchs; 696 ansich = cast(char) SendMessageA(hwnd, EM_GETPASSWORDCHAR, 0, 0); 697 //chs = fromAnsi((&ansich)[0 .. 1], 1); 698 chs = fromAnsi(&ansich, 1); 699 dchs = utf8stringtoUtf32string(chs); 700 if (dchs.length == 1) { 701 return dchs[0]; // ? 702 } 703 return 0; 704 } 705 } 706 707 LRESULT sendMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 708 if (useUnicode) { 709 version (STATIC_UNICODE_SEND_MESSAGE) { 710 alias proc = SendMessageW; 711 } else { 712 SendMessageWProc proc; 713 proc = _loadSendMessageW(); 714 } 715 716 return proc(hwnd, msg, wparam, lparam); 717 } else { 718 return SendMessageA(hwnd, msg, wparam, lparam); 719 } 720 } 721 722 LRESULT sendMessage(HWND hwnd, UINT msg, WPARAM wparam, Dstring lparam, bool safe = true) { 723 if (useUnicode) { 724 version (STATIC_UNICODE_SEND_MESSAGE) { 725 alias proc = SendMessageW; 726 } else { 727 SendMessageWProc proc; 728 proc = _loadSendMessageW(); 729 } 730 731 return proc(hwnd, msg, wparam, cast(LPARAM) toUnicodez(lparam)); 732 } else { 733 return SendMessageA(hwnd, msg, wparam, cast(LPARAM) toAnsiz(lparam, safe)); // Can't assume unsafeAnsiz() is OK here. 734 } 735 } 736 737 LRESULT sendMessageUnsafe(HWND hwnd, UINT msg, WPARAM wparam, Dstring lparam) { 738 return sendMessage(hwnd, msg, wparam, lparam, false); 739 } 740 741 version = STATIC_UNICODE_CALL_WINDOW_PROC; 742 743 LRESULT callWindowProc(WNDPROC lpPrevWndFunc, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 744 if (useUnicode) { 745 version (STATIC_UNICODE_CALL_WINDOW_PROC) { 746 alias proc = CallWindowProcW; 747 } else { 748 enum NAME = "CallWindowProcW"; 749 static CallWindowProcWProc proc = null; 750 751 if (!proc) { 752 proc = cast(CallWindowProcWProc) GetProcAddress(user32, NAME.ptr); 753 if (!proc) { 754 getProcErr(NAME); 755 } 756 } 757 } 758 759 return proc(lpPrevWndFunc, hwnd, msg, wparam, lparam); 760 } else { 761 return CallWindowProcA(lpPrevWndFunc, hwnd, msg, wparam, lparam); 762 } 763 } 764 765 UINT registerClipboardFormat(Dstring formatName) { 766 if (useUnicode) { 767 version (STATIC_UNICODE) { 768 alias proc = RegisterClipboardFormatW; 769 } else { 770 enum NAME = "RegisterClipboardFormatW"; 771 static RegisterClipboardFormatWProc proc = null; 772 773 if (!proc) { 774 proc = cast(RegisterClipboardFormatWProc) GetProcAddress(user32, NAME.ptr); 775 if (!proc) { 776 getProcErr(NAME); 777 } 778 } 779 } 780 781 return proc(toUnicodez(formatName)); 782 } else { 783 return RegisterClipboardFormatA(unsafeAnsiz(formatName)); 784 } 785 } 786 787 Dstring getClipboardFormatName(UINT format) { 788 if (useUnicode) { 789 version (STATIC_UNICODE) { 790 alias proc = GetClipboardFormatNameW; 791 } else { 792 enum NAME = "GetClipboardFormatNameW"; 793 static GetClipboardFormatNameWProc proc = null; 794 795 if (!proc) { 796 proc = cast(GetClipboardFormatNameWProc) GetProcAddress(user32, NAME.ptr); 797 if (!proc) { 798 getProcErr(NAME); 799 } 800 } 801 } 802 803 wchar[] buf; 804 int len; 805 buf = new wchar[64]; 806 len = proc(format, buf.ptr, buf.length); 807 if (!len) { 808 return null; 809 } 810 return fromUnicode(buf.ptr, len); 811 } else { 812 char[] buf; 813 int len; 814 buf = new char[64]; 815 len = GetClipboardFormatNameA(format, buf.ptr, buf.length); 816 if (!len) { 817 return null; 818 } 819 return fromAnsi(buf.ptr, len); 820 } 821 } 822 823 // On Windows 9x, the number of characters cannot exceed 8192. 824 int drawTextEx(HDC hdc, Dstring text, LPRECT lprc, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) { 825 // Note: an older version of MSDN says cchText should be -1 for a null terminated string, 826 // whereas the newer MSDN says 1. Lets just play it safe and use a local null terminated 827 // string when the length is 1 so that it won't continue reading past the 1 character, 828 // reguardless of which MSDN version is correct. 829 830 if (useUnicode) { 831 version (STATIC_UNICODE) { 832 alias proc = DrawTextExW; 833 } else { 834 enum NAME = "DrawTextExW"; 835 static DrawTextExWProc proc = null; 836 837 if (!proc) { 838 proc = cast(DrawTextExWProc) GetProcAddress(user32, NAME.ptr); 839 if (!proc) { 840 getProcErr(NAME); 841 } 842 } 843 } 844 845 /+ 846 wchar* strz; 847 strz = toUnicodez(text); 848 return proc(hdc, strz, -1, lprc, dwDTFormat, lpDTParams); 849 +/ 850 Dwstring str; 851 wchar[2] tempStr; 852 str = toUnicode(text); 853 if (str.length == 1) { 854 tempStr[0] = str[0]; 855 tempStr[1] = 0; 856 //str = tempStr[0 .. 1]; 857 str = cast(Dwstring) tempStr[0 .. 1]; // Needed in D2. 858 } 859 //return proc(hdc, str.ptr, str.length, lprc, dwDTFormat, lpDTParams); 860 return proc(hdc, cast(wchar*) str.ptr, str.length, lprc, dwDTFormat, lpDTParams); // Needed in D2. 861 } else { 862 /+ 863 char* strz; 864 strz = unsafeAnsiz(text); 865 return DrawTextExA(hdc, strz, -1, lprc, dwDTFormat, lpDTParams); 866 +/ 867 Dstring str; 868 char[2] tempStr; 869 str = unsafeAnsi(text); 870 if (str.length == 1) { 871 tempStr[0] = str[0]; 872 tempStr[1] = 0; 873 //str = tempStr[0 .. 1]; 874 str = cast(Dstring) tempStr[0 .. 1]; // Needed in D2. 875 } 876 //return DrawTextExA(hdc, str.ptr, str.length, lprc, dwDTFormat, lpDTParams); 877 return DrawTextExA(hdc, cast(char*) str.ptr, str.length, lprc, dwDTFormat, lpDTParams); // Needed in D2. 878 } 879 } 880 881 Dstring getCommandLine() { 882 // Windows 9x supports GetCommandLineW(). 883 return dfl.internal.utf.fromUnicodez(GetCommandLineW()); 884 } 885 886 /* MSDN: 887 The current directory state written by the SetCurrentDirectory function 888 is stored as a global variable in each process, therefore multithreaded 889 applications cannot reliably use this value without possible data 890 corruption from other threads that may also be reading or setting this 891 value. This limitation also applies to the GetCurrentDirectory and 892 GetFullPathName functions. 893 */ 894 // This doesn't prevent the problem, but it can minimize it. 895 // e.g. file dialogs set it. 896 //class CurDirLockType { } 897 898 BOOL setCurrentDirectory(Dstring pathName) { 899 //synchronized(typeid(CurDirLockType)) 900 { 901 if (useUnicode) { 902 version (STATIC_UNICODE) { 903 alias proc = SetCurrentDirectoryW; 904 } else { 905 enum NAME = "SetCurrentDirectoryW"; 906 static SetCurrentDirectoryWProc proc = null; 907 908 if (!proc) { 909 proc = cast(SetCurrentDirectoryWProc) GetProcAddress(kernel32, NAME.ptr); 910 if (!proc) { 911 getProcErr(NAME); 912 } 913 } 914 } 915 916 return proc(toUnicodez(pathName)); 917 } else { 918 return SetCurrentDirectoryA(unsafeAnsiz(pathName)); 919 } 920 } 921 } 922 923 Dstring getCurrentDirectory() { 924 //synchronized(typeid(CurDirLockType)) 925 { 926 if (useUnicode) { 927 version (STATIC_UNICODE) { 928 alias proc = GetCurrentDirectoryW; 929 } else { 930 enum NAME = "GetCurrentDirectoryW"; 931 static GetCurrentDirectoryWProc proc = null; 932 933 if (!proc) { 934 proc = cast(GetCurrentDirectoryWProc) GetProcAddress(kernel32, NAME.ptr); 935 if (!proc) { 936 getProcErr(NAME); 937 } 938 } 939 } 940 941 wchar* buf; 942 int len; 943 len = proc(0, null); 944 buf = (new wchar[len]).ptr; 945 len = proc(len, buf); 946 if (!len) { 947 return null; 948 } 949 return fromUnicode(buf, len); 950 } else { 951 char* buf; 952 int len; 953 len = GetCurrentDirectoryA(0, null); 954 buf = (new char[len]).ptr; 955 len = GetCurrentDirectoryA(len, buf); 956 if (!len) { 957 return null; 958 } 959 return fromAnsi(buf, len); 960 } 961 } 962 } 963 964 Dstring getFullPathName(Dstring fileName) { 965 //synchronized(typeid(CurDirLockType)) 966 { 967 DWORD len; 968 969 if (useUnicode) { 970 version (STATIC_UNICODE) { 971 alias proc = GetFullPathNameW; 972 } else { 973 enum NAME = "GetFullPathNameW"; 974 static GetFullPathNameWProc proc = null; 975 976 if (!proc) { 977 proc = cast(GetFullPathNameWProc) GetProcAddress(kernel32, NAME.ptr); 978 if (!proc) { 979 getProcErr(NAME); 980 } 981 } 982 } 983 984 auto fnw = toUnicodez(fileName); 985 len = proc(fnw, 0, null, null); 986 if (!len) { 987 return null; 988 } 989 wchar[260] _wbuf; 990 wchar[] wbuf = _wbuf; 991 if (len > _wbuf.sizeof) { 992 wbuf = new wchar[len]; 993 } 994 len = proc(fnw, wbuf.length, wbuf.ptr, null); 995 assert(len < wbuf.length); 996 return fromUnicode(wbuf.ptr, len); 997 } else { 998 auto fna = unsafeAnsiz(fileName); 999 len = GetFullPathNameA(fna, 0, null, null); 1000 if (!len) { 1001 return null; 1002 } 1003 char[260] _abuf; 1004 char[] abuf = _abuf; 1005 if (len > _abuf.sizeof) { 1006 abuf = new char[len]; 1007 } 1008 len = GetFullPathNameA(fna, abuf.length, abuf.ptr, null); 1009 assert(len < abuf.length); 1010 return fromAnsi(abuf.ptr, len); 1011 } 1012 } 1013 } 1014 1015 Dstring getComputerName() { 1016 if (useUnicode) { 1017 version (STATIC_UNICODE) { 1018 alias proc = GetComputerNameW; 1019 } else { 1020 enum NAME = "GetComputerNameW"; 1021 static GetComputerNameWProc proc = null; 1022 1023 if (!proc) { 1024 proc = cast(GetComputerNameWProc) GetProcAddress(kernel32, NAME.ptr); 1025 if (!proc) { 1026 getProcErr(NAME); 1027 } 1028 } 1029 } 1030 1031 wchar[] buf; 1032 DWORD len = MAX_COMPUTERNAME_LENGTH + 1; 1033 buf = new wchar[len]; 1034 if (!proc(buf.ptr, &len)) { 1035 return null; 1036 } 1037 return fromUnicode(buf.ptr, len); 1038 } else { 1039 char[] buf; 1040 DWORD len = MAX_COMPUTERNAME_LENGTH + 1; 1041 buf = new char[len]; 1042 if (!GetComputerNameA(buf.ptr, &len)) { 1043 return null; 1044 } 1045 return fromAnsi(buf.ptr, len); 1046 } 1047 } 1048 1049 Dstring getSystemDirectory() { 1050 if (useUnicode) { 1051 version (STATIC_UNICODE) { 1052 alias proc = GetSystemDirectoryW; 1053 } else { 1054 enum NAME = "GetSystemDirectoryW"; 1055 static GetSystemDirectoryWProc proc = null; 1056 1057 if (!proc) { 1058 proc = cast(GetSystemDirectoryWProc) GetProcAddress(kernel32, NAME.ptr); 1059 if (!proc) { 1060 getProcErr(NAME); 1061 } 1062 } 1063 } 1064 1065 wchar[] buf; 1066 UINT len; 1067 buf = new wchar[MAX_PATH]; 1068 len = proc(buf.ptr, buf.length); 1069 if (!len) { 1070 return null; 1071 } 1072 return fromUnicode(buf.ptr, len); 1073 } else { 1074 char[] buf; 1075 UINT len; 1076 buf = new char[MAX_PATH]; 1077 len = GetSystemDirectoryA(buf.ptr, buf.length); 1078 if (!len) { 1079 return null; 1080 } 1081 return fromAnsi(buf.ptr, len); 1082 } 1083 } 1084 1085 Dstring getUserName() { 1086 if (useUnicode) { 1087 version (STATIC_UNICODE) { 1088 alias proc = GetUserNameW; 1089 } else { 1090 enum NAME = "GetUserNameW"; 1091 static GetUserNameWProc proc = null; 1092 1093 if (!proc) { 1094 proc = cast(GetUserNameWProc) GetProcAddress(advapi32, NAME.ptr); 1095 if (!proc) { 1096 getProcErr(NAME); 1097 } 1098 } 1099 } 1100 1101 wchar[256 + 1] buf; 1102 DWORD len = buf.length; 1103 if (!proc(buf.ptr, &len) || !len || !--len) { // Also remove null-terminator. 1104 return null; 1105 } 1106 return fromUnicode(buf.ptr, len); 1107 } else { 1108 char[256 + 1] buf; 1109 DWORD len = buf.length; 1110 if (!GetUserNameA(buf.ptr, &len) || !len || !--len) { // Also remove null-terminator. 1111 return null; 1112 } 1113 return fromAnsi(buf.ptr, len); 1114 } 1115 } 1116 1117 // Returns 0 on failure. 1118 DWORD expandEnvironmentStrings(Dstring src, out Dstring result) { 1119 if (useUnicode) { 1120 version (STATIC_UNICODE) { 1121 alias proc = ExpandEnvironmentStringsW; 1122 } else { 1123 enum NAME = "ExpandEnvironmentStringsW"; 1124 static ExpandEnvironmentStringsWProc proc = null; 1125 1126 if (!proc) { 1127 proc = cast(ExpandEnvironmentStringsWProc) GetProcAddress(kernel32, NAME.ptr); 1128 if (!proc) { 1129 getProcErr(NAME); 1130 } 1131 } 1132 } 1133 1134 wchar* dest; 1135 DWORD len; 1136 1137 auto strz = toUnicodez(src); 1138 len = proc(strz, null, 0); 1139 if (!len) { 1140 return 0; 1141 } 1142 dest = (new wchar[len]).ptr; 1143 len = proc(strz, dest, len); 1144 if (!len) { 1145 return 0; 1146 } 1147 result = fromUnicode(dest, len - 1); 1148 return len; 1149 } else { 1150 char* dest; 1151 DWORD len; 1152 1153 auto strz = unsafeAnsiz(src); 1154 len = ExpandEnvironmentStringsA(strz, null, 0); 1155 if (!len) { 1156 return 0; 1157 } 1158 dest = (new char[len]).ptr; 1159 len = ExpandEnvironmentStringsA(strz, dest, len); 1160 if (!len) { 1161 return 0; 1162 } 1163 result = fromAnsi(dest, len - 1); 1164 return len; 1165 } 1166 } 1167 1168 Dstring getEnvironmentVariable(Dstring name) { 1169 if (useUnicode) { 1170 version (STATIC_UNICODE) { 1171 alias proc = GetEnvironmentVariableW; 1172 } else { 1173 enum NAME = "GetEnvironmentVariableW"; 1174 static GetEnvironmentVariableWProc proc = null; 1175 1176 if (!proc) { 1177 proc = cast(GetEnvironmentVariableWProc) GetProcAddress(kernel32, NAME.ptr); 1178 if (!proc) { 1179 getProcErr(NAME); 1180 } 1181 } 1182 } 1183 1184 wchar* buf; 1185 DWORD len; 1186 auto strz = toUnicodez(name); 1187 len = proc(strz, null, 0); 1188 if (!len) { 1189 return null; 1190 } 1191 buf = (new wchar[len]).ptr; 1192 len = proc(strz, buf, len); 1193 return fromUnicode(buf, len); 1194 } else { 1195 char* buf; 1196 DWORD len; 1197 auto strz = unsafeAnsiz(name); 1198 len = GetEnvironmentVariableA(strz, null, 0); 1199 if (!len) { 1200 return null; 1201 } 1202 buf = (new char[len]).ptr; 1203 len = GetEnvironmentVariableA(strz, buf, len); 1204 return fromAnsi(buf, len); 1205 } 1206 } 1207 1208 int messageBox(HWND hWnd, Dstring text, Dstring caption, UINT uType) { 1209 // Windows 9x supports MessageBoxW(). 1210 return MessageBoxW(hWnd, toUnicodez(text), toUnicodez(caption), uType); 1211 } 1212 1213 struct WndClass { 1214 union { 1215 WNDCLASSW wcw; 1216 WNDCLASSA wca; 1217 } 1218 1219 alias wc = wcw; 1220 1221 Dstring className; 1222 } 1223 1224 ATOM registerClass(ref WndClass wc) { 1225 if (useUnicode) { 1226 version (STATIC_UNICODE) { 1227 alias proc = RegisterClassW; 1228 } else { 1229 enum NAME = "RegisterClassW"; 1230 static RegisterClassWProc proc = null; 1231 1232 if (!proc) { 1233 proc = cast(RegisterClassWProc) GetProcAddress(user32, NAME.ptr); 1234 if (!proc) { 1235 getProcErr(NAME); 1236 } 1237 } 1238 } 1239 1240 wc.wcw.lpszClassName = toUnicodez(wc.className); 1241 return proc(&wc.wcw); 1242 } else { 1243 wc.wca.lpszClassName = unsafeAnsiz(wc.className); 1244 return RegisterClassA(&wc.wca); 1245 } 1246 } 1247 1248 BOOL getClassInfo(HINSTANCE hinst, Dstring className, ref WndClass wc) { 1249 wc.className = className; // ? 1250 1251 if (useUnicode) { 1252 version (STATIC_UNICODE) { 1253 alias proc = GetClassInfoW; 1254 } else { 1255 enum NAME = "GetClassInfoW"; 1256 static GetClassInfoWProc proc = null; 1257 1258 if (!proc) { 1259 proc = cast(GetClassInfoWProc) GetProcAddress(user32, NAME.ptr); 1260 if (!proc) { 1261 getProcErr(NAME); 1262 } 1263 } 1264 } 1265 1266 return proc(hinst, toUnicodez(className), &wc.wcw); 1267 } else { 1268 return GetClassInfoA(hinst, unsafeAnsiz(className), &wc.wca); 1269 } 1270 } 1271 1272 // Shouldn't have been implemented this way. 1273 deprecated BOOL getTextExtentPoint32(HDC hdc, Dstring text, LPSIZE lpSize) { 1274 if (useUnicode) { 1275 version (STATIC_UNICODE) { 1276 alias proc = GetTextExtentPoint32W; 1277 } else { 1278 enum NAME = "GetTextExtentPoint32W"; 1279 static GetTextExtentPoint32WProc proc = null; 1280 1281 if (!proc) { 1282 proc = cast(GetTextExtentPoint32WProc) GetProcAddress(gdi32, NAME.ptr); 1283 if (!proc) { 1284 getProcErr(NAME); 1285 } 1286 } 1287 } 1288 1289 Dwstring str; 1290 str = toUnicode(text); 1291 return proc(hdc, str.ptr, str.length, lpSize); 1292 } else { 1293 // Using GetTextExtentPoint32A here even though W is supported in order 1294 // to keep the measurements accurate with DrawTextA. 1295 Dstring str; 1296 str = unsafeAnsi(text); 1297 return GetTextExtentPoint32A(hdc, str.ptr, str.length, lpSize); 1298 } 1299 } 1300 1301 Dstring dragQueryFile(HDROP hDrop, UINT iFile) { 1302 if (iFile >= 0xFFFFFFFF) { 1303 return null; 1304 } 1305 1306 if (useUnicode) { 1307 version (STATIC_UNICODE) { 1308 alias proc = DragQueryFileW; 1309 } else { 1310 enum NAME = "DragQueryFileW"; 1311 static DragQueryFileWProc proc = null; 1312 1313 if (!proc) { 1314 proc = cast(DragQueryFileWProc) GetProcAddress(GetModuleHandleA("shell32.dll"), 1315 NAME.ptr); 1316 if (!proc) { 1317 getProcErr(NAME); 1318 } 1319 } 1320 } 1321 1322 wchar[] str; 1323 UINT len; 1324 len = proc(hDrop, iFile, null, 0); 1325 if (!len) { 1326 return null; 1327 } 1328 str = new wchar[len + 1]; 1329 proc(hDrop, iFile, str.ptr, str.length); 1330 return fromUnicode(str.ptr, len); 1331 } else { 1332 char[] str; 1333 UINT len; 1334 len = DragQueryFileA(hDrop, iFile, null, 0); 1335 if (!len) { 1336 return null; 1337 } 1338 str = new char[len + 1]; 1339 DragQueryFileA(hDrop, iFile, str.ptr, str.length); 1340 return fromAnsi(str.ptr, len); 1341 } 1342 } 1343 1344 // Just gets the number of files. 1345 UINT dragQueryFile(HDROP hDrop) { 1346 return DragQueryFileA(hDrop, 0xFFFFFFFF, null, 0); 1347 } 1348 1349 HANDLE createFile(Dstring fileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, 1350 DWORD dwCreationDistribution, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { 1351 if (useUnicode) { 1352 return CreateFileW(toUnicodez(fileName), dwDesiredAccess, dwShareMode, 1353 lpSecurityAttributes, dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile); 1354 } else { 1355 return CreateFileA(unsafeAnsiz(fileName), dwDesiredAccess, dwShareMode, 1356 lpSecurityAttributes, dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile); 1357 } 1358 } 1359 1360 version = STATIC_UNICODE_DEF_WINDOW_PROC; 1361 1362 LRESULT defWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 1363 if (useUnicode) { 1364 version (STATIC_UNICODE_DEF_WINDOW_PROC) { 1365 alias proc = DefWindowProcW; 1366 } else { 1367 enum NAME = "DefWindowProcW"; 1368 static DefWindowProcWProc proc = null; 1369 1370 if (!proc) { 1371 proc = cast(DefWindowProcWProc) GetProcAddress(user32, NAME.ptr); 1372 if (!proc) { 1373 getProcErr(NAME); 1374 } 1375 } 1376 } 1377 1378 return proc(hwnd, msg, wparam, lparam); 1379 } else { 1380 return DefWindowProcA(hwnd, msg, wparam, lparam); 1381 } 1382 } 1383 1384 LRESULT defDlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 1385 if (useUnicode) { 1386 version (STATIC_UNICODE_DEF_WINDOW_PROC) { 1387 alias proc = DefDlgProcW; 1388 } else { 1389 enum NAME = "DefDlgProcW"; 1390 static DefDlgProcWProc proc = null; 1391 1392 if (!proc) { 1393 proc = cast(DefDlgProcWProc) GetProcAddress(user32, NAME.ptr); 1394 if (!proc) { 1395 getProcErr(NAME); 1396 } 1397 } 1398 } 1399 1400 return proc(hwnd, msg, wparam, lparam); 1401 } else { 1402 return DefDlgProcA(hwnd, msg, wparam, lparam); 1403 } 1404 } 1405 1406 LRESULT defFrameProc(HWND hwnd, HWND hwndMdiClient, UINT msg, WPARAM wparam, LPARAM lparam) { 1407 if (useUnicode) { 1408 version (STATIC_UNICODE_DEF_WINDOW_PROC) { 1409 alias proc = DefFrameProcW; 1410 } else { 1411 enum NAME = "DefFrameProcW"; 1412 static DefFrameProcWProc proc = null; 1413 1414 if (!proc) { 1415 proc = cast(DefFrameProcWProc) GetProcAddress(user32, NAME.ptr); 1416 if (!proc) { 1417 getProcErr(NAME); 1418 } 1419 } 1420 } 1421 1422 return proc(hwnd, hwndMdiClient, msg, wparam, lparam); 1423 } else { 1424 return DefFrameProcA(hwnd, hwndMdiClient, msg, wparam, lparam); 1425 } 1426 } 1427 1428 LRESULT defMDIChildProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 1429 if (useUnicode) { 1430 version (STATIC_UNICODE_DEF_WINDOW_PROC) { 1431 alias proc = DefMDIChildProcW; 1432 } else { 1433 enum NAME = "DefMDIChildProcW"; 1434 static DefMDIChildProcWProc proc = null; 1435 1436 if (!proc) { 1437 proc = cast(DefMDIChildProcWProc) GetProcAddress(user32, NAME.ptr); 1438 if (!proc) { 1439 getProcErr(NAME); 1440 } 1441 } 1442 } 1443 1444 return proc(hwnd, msg, wparam, lparam); 1445 } else { 1446 return DefMDIChildProcA(hwnd, msg, wparam, lparam); 1447 } 1448 } 1449 1450 version = STATIC_UNICODE_PEEK_MESSAGE; 1451 version = STATIC_UNICODE_DISPATCH_MESSAGE; 1452 1453 LONG dispatchMessage(MSG* pmsg) { 1454 if (useUnicode) { 1455 version (STATIC_UNICODE_DISPATCH_MESSAGE) { 1456 alias dispatchproc = DispatchMessageW; 1457 } else { 1458 enum DISPATCHNAME = "DispatchMessageW"; 1459 static DispatchMessageWProc dispatchproc = null; 1460 1461 if (!dispatchproc) { 1462 dispatchproc = cast(DispatchMessageWProc) GetProcAddress(user32, DISPATCHNAME); 1463 if (!dispatchproc) { 1464 getProcErr(DISPATCHNAME); 1465 } 1466 } 1467 } 1468 1469 return dispatchproc(pmsg); 1470 } else { 1471 return DispatchMessageA(pmsg); 1472 } 1473 } 1474 1475 BOOL peekMessage(MSG* pmsg, HWND hwnd = HWND.init, UINT wmFilterMin = 0, 1476 UINT wmFilterMax = 0, UINT removeMsg = PM_NOREMOVE) { 1477 if (useUnicode) { 1478 version (STATIC_UNICODE_PEEK_MESSAGE) { 1479 alias peekproc = PeekMessageW; 1480 } else { 1481 enum PEEKNAME = "PeekMessageW"; 1482 static PeekMessageWProc peekproc = null; 1483 1484 if (!peekproc) { 1485 peekproc = cast(PeekMessageWProc) GetProcAddress(user32, PEEKNAME); 1486 if (!peekproc) { 1487 getProcErr(PEEKNAME); 1488 } 1489 } 1490 } 1491 1492 /+ 1493 // Using PeekMessageA to test if the window is unicod. 1494 if(!PeekMessageA(pmsg, hwnd, wmFilterMin, wmFilterMax, PM_NOREMOVE)) { // Don't remove to test if unicode. 1495 return 0; 1496 } 1497 if(!IsWindowUnicode(pmsg.hwnd)) { // Window is not unicode. 1498 if(removeMsg == PM_NOREMOVE) { 1499 return 1; // No need to do extra work here. 1500 } 1501 return PeekMessageA(pmsg, hwnd, wmFilterMin, wmFilterMax, removeMsg); 1502 } else { // Window is unicode. 1503 return peekproc(pmsg, hwnd, wmFilterMin, wmFilterMax, removeMsg); 1504 } 1505 +/ 1506 // Since I already know useUnicode, use PeekMessageW to test if the window is unicode. 1507 if (!peekproc(pmsg, hwnd, wmFilterMin, wmFilterMax, PM_NOREMOVE)) { // Don't remove to test if unicode. 1508 return 0; 1509 } 1510 if (!IsWindowUnicode(pmsg.hwnd)) { // Window is not unicode. 1511 return PeekMessageA(pmsg, hwnd, wmFilterMin, wmFilterMax, removeMsg); 1512 } else { // Window is unicode. 1513 if (removeMsg == PM_NOREMOVE) { 1514 return 1; // No need to do extra work here. 1515 } 1516 return peekproc(pmsg, hwnd, wmFilterMin, wmFilterMax, removeMsg); 1517 } 1518 } else { 1519 return PeekMessageA(pmsg, hwnd, wmFilterMin, wmFilterMax, removeMsg); 1520 } 1521 } 1522 1523 BOOL getMessage(MSG* pmsg, HWND hwnd = HWND.init, UINT wmFilterMin = 0, UINT wmFilterMax = 0) { 1524 if (!WaitMessage()) { 1525 return -1; 1526 } 1527 if (!peekMessage(pmsg, hwnd, wmFilterMin, wmFilterMax, PM_REMOVE)) { 1528 return -1; 1529 } 1530 if (WM_QUIT == pmsg.message) { 1531 return 0; 1532 } 1533 return 1; 1534 } 1535 1536 BOOL isDialogMessage(HWND hwnd, MSG* pmsg) { 1537 if (useUnicode) { 1538 version (STATIC_UNICODE) { 1539 alias proc = IsDialogMessageW; 1540 } else { 1541 enum NAME = "IsDialogMessageW"; 1542 static IsDialogMessageWProc proc = null; 1543 1544 if (!proc) { 1545 proc = cast(IsDialogMessageWProc) GetProcAddress(user32, NAME.ptr); 1546 if (!proc) { 1547 getProcErr(NAME); 1548 } 1549 } 1550 } 1551 1552 return proc(hwnd, pmsg); 1553 } else { 1554 return IsDialogMessageA(hwnd, pmsg); 1555 } 1556 } 1557 1558 HANDLE findFirstChangeNotification(Dstring pathName, BOOL watchSubtree, DWORD notifyFilter) { 1559 if (useUnicode) { 1560 version (STATIC_UNICODE) { 1561 alias proc = FindFirstChangeNotificationW; 1562 } else { 1563 enum NAME = "FindFirstChangeNotificationW"; 1564 static FindFirstChangeNotificationWProc proc = null; 1565 1566 if (!proc) { 1567 proc = cast(FindFirstChangeNotificationWProc) GetProcAddress(kernel32, NAME.ptr); 1568 if (!proc) { 1569 getProcErr(NAME); 1570 } 1571 } 1572 } 1573 1574 return proc(toUnicodez(pathName), watchSubtree, notifyFilter); 1575 } else { 1576 return FindFirstChangeNotificationA(unsafeAnsiz(pathName), watchSubtree, notifyFilter); 1577 } 1578 } 1579 1580 HINSTANCE loadLibraryEx(Dstring libFileName, DWORD flags) { 1581 if (useUnicode) { 1582 version (STATIC_UNICODE) { 1583 alias proc = LoadLibraryExW; 1584 } else { 1585 enum NAME = "LoadLibraryExW"; 1586 static LoadLibraryExWProc proc = null; 1587 1588 if (!proc) { 1589 proc = cast(LoadLibraryExWProc) GetProcAddress(kernel32, NAME.ptr); 1590 if (!proc) { 1591 getProcErr(NAME); 1592 } 1593 } 1594 } 1595 1596 return proc(toUnicodez(libFileName), HANDLE.init, flags); 1597 } else { 1598 return LoadLibraryExA(unsafeAnsiz(libFileName), HANDLE.init, flags); 1599 } 1600 } 1601 1602 BOOL _setMenuItemInfoW(HMENU hMenu, UINT uItem, BOOL fByPosition, LPMENUITEMINFOW lpmii) { // package 1603 if (useUnicode) { 1604 version (STATIC_UNICODE) { 1605 alias proc = SetMenuItemInfoW; 1606 } else { 1607 enum NAME = "SetMenuItemInfoW"; 1608 static SetMenuItemInfoWProc proc = null; 1609 1610 if (!proc) { 1611 proc = cast(SetMenuItemInfoWProc) GetProcAddress(user32, NAME.ptr); 1612 if (!proc) { 1613 getProcErr(NAME); 1614 } 1615 } 1616 } 1617 1618 return proc(hMenu, uItem, fByPosition, lpmii); 1619 } else { 1620 assert(0); 1621 } 1622 } 1623 1624 BOOL _insertMenuItemW(HMENU hMenu, UINT uItem, BOOL fByPosition, LPMENUITEMINFOW lpmii) { // package 1625 if (useUnicode) { 1626 version (STATIC_UNICODE) { 1627 alias proc = InsertMenuItemW; 1628 } else { 1629 enum NAME = "InsertMenuItemW"; 1630 static InsertMenuItemWProc proc = null; 1631 1632 if (!proc) { 1633 proc = cast(InsertMenuItemWProc) GetProcAddress(user32, NAME.ptr); 1634 if (!proc) { 1635 getProcErr(NAME); 1636 } 1637 } 1638 } 1639 1640 return proc(hMenu, uItem, fByPosition, lpmii); 1641 } else { 1642 assert(0); 1643 } 1644 } 1645 1646 Dstring regQueryValueString(HKEY hkey, Dstring valueName, LPDWORD lpType = null) { 1647 DWORD _type; 1648 if (!lpType) { 1649 lpType = &_type; 1650 } 1651 1652 DWORD sz; 1653 1654 if (useUnicode) { 1655 version (STATIC_UNICODE) { 1656 alias proc = RegQueryValueExW; 1657 } else { 1658 enum NAME = "RegQueryValueExW"; 1659 static RegQueryValueExWProc proc = null; 1660 1661 if (!proc) { 1662 proc = cast(RegQueryValueExWProc) GetProcAddress(advapi32, NAME.ptr); 1663 if (!proc) { 1664 getProcErr(NAME); 1665 } 1666 } 1667 } 1668 1669 //sz = 0; 1670 auto lpValueName = toUnicodez(valueName); 1671 proc(hkey, lpValueName, null, lpType, null, &sz); 1672 if (!sz || (REG_SZ != *lpType && REG_EXPAND_SZ != *lpType)) { 1673 return null; 1674 } 1675 wchar[] ws = new wchar[sz]; 1676 if (ERROR_SUCCESS != proc(hkey, lpValueName, null, null, cast(LPBYTE) ws.ptr, &sz)) { 1677 return null; 1678 } 1679 //return fromUnicode(ws.ptr, ws.length - 1); // Somehow ends up throwing invalid UTF-16. 1680 return fromUnicodez(ws.ptr); 1681 } else { 1682 //sz = 0; 1683 auto lpValueName = toAnsiz(valueName); 1684 RegQueryValueExA(hkey, lpValueName, null, lpType, null, &sz); 1685 if (!sz || (REG_SZ != *lpType && REG_EXPAND_SZ != *lpType)) { 1686 return null; 1687 } 1688 char[] s = new char[sz]; 1689 if (ERROR_SUCCESS != RegQueryValueExA(hkey, lpValueName, null, null, 1690 cast(LPBYTE) s.ptr, &sz)) { 1691 return null; 1692 } 1693 //return fromAnsi(s.ptr, s.length - 1); 1694 return fromAnsiz(s.ptr); 1695 } 1696 } 1697 1698 struct LogFont { 1699 union { 1700 LOGFONTW lfw; 1701 LOGFONTA lfa; 1702 } 1703 1704 alias lf = lfw; 1705 1706 Dstring faceName; 1707 } 1708 1709 HFONT createFontIndirect(ref LogFont lf) { 1710 if (useUnicode) { 1711 version (STATIC_UNICODE) { 1712 alias proc = CreateFontIndirectW; 1713 } else { 1714 enum NAME = "CreateFontIndirectW"; 1715 static CreateFontIndirectWProc proc = null; 1716 1717 if (!proc) { 1718 proc = cast(CreateFontIndirectWProc) GetProcAddress(gdi32, NAME.ptr); 1719 if (!proc) { 1720 getProcErr(NAME); 1721 } 1722 } 1723 } 1724 1725 Dwstring ws = toUnicode(lf.faceName); 1726 if (ws.length >= LF_FACESIZE) { 1727 ws = ws[0 .. LF_FACESIZE - 1]; // ? 1728 } 1729 foreach (idx, wch; ws) { 1730 lf.lfw.lfFaceName[idx] = wch; 1731 } 1732 lf.lfw.lfFaceName[ws.length] = 0; 1733 1734 return proc(&lf.lfw); 1735 } else { 1736 Dstring as = toAnsi(lf.faceName); 1737 if (as.length >= LF_FACESIZE) { 1738 as = as[0 .. LF_FACESIZE - 1]; // ? 1739 } 1740 foreach (idx, ach; as) { 1741 lf.lfa.lfFaceName[idx] = ach; 1742 } 1743 lf.lfa.lfFaceName[as.length] = 0; 1744 1745 return CreateFontIndirectA(&lf.lfa); 1746 } 1747 } 1748 1749 // GetObject for a LogFont. 1750 int getLogFont(HFONT hf, ref LogFont lf) { 1751 if (useUnicode) { 1752 version (STATIC_UNICODE) { 1753 alias proc = GetObjectW; 1754 } else { 1755 enum NAME = "GetObjectW"; 1756 static GetObjectWProc proc = null; 1757 1758 if (!proc) { 1759 proc = cast(GetObjectWProc) GetProcAddress(gdi32, NAME.ptr); 1760 if (!proc) { 1761 getProcErr(NAME); 1762 } 1763 } 1764 } 1765 1766 if (LOGFONTW.sizeof != proc(hf, LOGFONTW.sizeof, &lf.lfw)) { 1767 return 0; 1768 } 1769 lf.faceName = fromUnicodez(lf.lfw.lfFaceName.ptr); 1770 return LOGFONTW.sizeof; 1771 } else { 1772 if (LOGFONTA.sizeof != GetObjectA(hf, LOGFONTA.sizeof, &lf.lfa)) { 1773 return 0; 1774 } 1775 lf.faceName = fromAnsiz(lf.lfa.lfFaceName.ptr); 1776 return LOGFONTA.sizeof; 1777 } 1778 }