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