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