Calling the Windows API functions

The Windows API provides a rich set of functionalities for applications. The entire Windows API is directly accessible from D. Here, we'll demonstrate this by popping up an information message box and a file chooser dialog box using the standard Win32 API functions.

Getting ready

First, make sure you have correctly installed the DMD compiler for Windows. If you want to build 64-bit applications, you must download and install Visual Studio (any version that supports C++ development, including Express) first because dmd on 64-bit Windows uses the Microsoft linker and libraries for better cross-language compatibility.

You'll also want to create or download the Windows API bindings since the Windows bindings that come with dmd are quite incomplete. You can create your own, as required, by copying and pasting the function and struct prototypes from MSDN.

If you are on 32 bit, you might also want to get the newer .lib files from Microsoft and convert them to the OMF format that the 32-bit dmd uses. This often isn't necessary, but if you want to use features from Windows Vista and newer versions, it likely will be. To do this, first download the Windows SDK from http://www.microsoft.com/en-us/download/details.aspx?id=8279, and then get the Basic Utilities Package (BUP) from http://digitalmars.com/ (you can purchase it for $15). Use coffimplib from the BUP on the .lib files from the SDK to generate the OMF-format libraries for dmd.

How to do it…

Let's call the Windows API functions by executing the following steps:

  1. Import core.sys.windows.windows.
  2. Create an OPENFILENAME structure and fill in the required fields.
  3. Call GetOpenFileName to pop up the file dialog.
  4. Use the MessageBox function to give feedback to the user.
  5. Link the file with comdlg32.lib by adding it to the dmd command line.

The code is as follows:

import core.sys.windows.window;
void main() {
        wchar[256] filenameBuffer;
        filenameBuffer[0] = 0;
        OPENFILENAMEW info;
        info.lStructSize = OPENFILENAMEW.sizeof;
        info.lpstrFilter = "Text Files*.txtImageFiles*.png;*.jpg"w.ptr;
        info.lpstrFile = filenameBuffer.ptr;
        info.nMaxFile = filenameBuffer.length;
        if(GetOpenFileNameW(&info)) {
            MessageBoxW(null, info.lpstrFile, "You picked"w.ptr, 0);
        }
}

How it works…

D understands the Windows calling convention. Calling any Windows function is possible by simply declaring the function prototype with extern(Windows).

Note

You may see extern(System) in the preceding code. The extern(System) function signifies the calling convention of system libraries on the current platform. In practice, this means extern(Windows) will be used on 32-bit Windows and extern(C) will be used everywhere else.

Windows functions that deal with strings come in two variants: ASCII and Unicode. These are denoted by the suffix A or W on the function names. In C and some D bindings, a UNICODE macro aliases the names to the appropriate suffix as needed. Here, we called the W functions explicitly for maximum compatibility and demonstration purposes.

MSDN often references TCHAR, TSTR, and so on. Like with the function prototypes, the meaning of TCHAR is different if you are using Unicode or ASCII macros. With ASCII, it should be char in D, whereas with Unicode, it should be wchar.

As D strings are Unicode, it is best to use the W versions of functions (it will let you pass strings to the A function, and it will work if the strings are all ASCII; however, if they include any non-ASCII characters, the string will be corrupted.) D has built-in support for wide-character strings (UTF-16) that can be used on Windows. The UTF-16 character type is wchar. An immutable array of wchar types is also called wstring, analogously to how arrays of UTF-8 characters are called string literals. The wstring literals are denoted with the w suffix, for example, this is a wstring literal, w. The wstring literals, like the string literals, are zero terminated. However, unlike string literals, they do not automatically convert to pointers; so, to pass a wstring literal to a Windows function, use the .ptr property. To pass a non-literal string to a Windows function, use std.utf.toUTFz!(wchar*)(your_string). This works both for wstring literals and UTF-8 strings—it appends the zero, converting the format only if necessary.

The GetOpenFileName uses a common pattern in Windows programming; it takes a struct, which knows its own size, as an argument. In C or C++, declaring these structs would typically be followed with a call to memset or ZeroMemory. This is not normally necessary in D because D, unlike C, initializes variables automatically. However, it is still important to initialize any static char/wchar array or float members since D initializes them by default to invalid values instead of zero (it does this in such a way that the use of an uninitialized value triggers an error as soon as possible). This is why we set filenameBuffer[0] = 0 to ensure it is properly terminated as an empty string. Pointers to strings and floats are by default initialized to null and may not have to be explicitly set.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.187.223