Sunday, December 6, 2009

Win32 Programming: How to Disable Unicode

It seems to be a mess for traditional C programmers to start with win32 when Unicode is enabled! All the texts, preceded `L` or `_T` are abstruse. Also most functions they are accustomed with doesn’t work because of incompatibility of data types and gives so many errors. What if we could disable Unicode and write program easily as most programs/software doesn’t strictly require to be Unicode!

We need to make a little change in project configuration. Open your project in Visual Studio IDE. Press Alt + F7.

There is an option named “General” under Configuration properties in the right side of the dialog box. Click it.

Under ‘project defaults’, there is a property called ‘Character Set’. Change its value from “Use Unicode Character Set” to “Use Multi-Byte Character Set” selecting from the drop down list as shown in the image below. Click the image to enlarge.



Now you can use normal string functions like strlen, sprintf etc in this program to manipulate strings. Here is a sample program demonstrating ANSI C behavior.


#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static TCHAR szWindowClass[] = "win32app";

static TCHAR szTitle[] = "SA OS Win32 Tutorial";

HINSTANCE hInst;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

    if (!RegisterClassEx(&wcex))
    {
        MessageBox(NULL,
            "Call to RegisterClassEx failed!",
            "Win32 Tutorial",
            NULL);

        return 1;
    }

    hInst = hInstance;

    HWND hWnd = CreateWindow(
        szWindowClass,
        szTitle,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        300, 280,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (!hWnd)
    {
        MessageBox(NULL,
            "Call to CreateWindow failed!",
            "Win32 Guided Tour",
            NULL);

        return 1;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    char *inst = "Non-unicode program";

    switch (message)
    {
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);

        TextOutA(hdc, 25, 75, inst, strlen(inst));
        inst = new char[101];
        sprintf_s(inst, 100, "Length of the string: %d", strlen(inst));
        TextOutA(hdc, 25, 95, inst, strlen(inst));

        EndPaint(hWnd, &ps);
        break;

        case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
        break;
    }

    return 0;
}

No comments:

Post a Comment