LESSON3:C++:Win32 API学習編
16個のWin32 GUIアプリの作成を通してWindows APIの基礎について学習します。 ここでのプログラムは基本的にはC言語の記述範囲ないでC++らしいコードは出てきていませんがかえってWindowsがどんな仕組みで動作しているのか 分かると思います。CodeBlocksでWin32 GUI projectを選んだ後に出てくるプロジェクトタイプを選ぶところでFrame projectを選んでmain.cpp1以外に ヘッダファイルはヘッダファイルの追加でリソースファイルは空のファイルをプロジェクにそれぞれ追加してコピペした後 Build→Runです。念のためターゲットがDebugでは作成されたWindowsアプリの他にDOS窓が開き表示されてしまいますが ReleaseではDOS窓は開きませんので安心してください。CodeBlocks IDEはすごく快適なプログラミング環境ですのでぜひ堪能していただきたいと思います。 なお、CodeBlocksのプロジェクトファイルは付属していませんがwin1からwin16までのソースコードと実行ファイルをまとめて tryC++.7zに用意しましたので利用してください。

w01.cpp The simplest Win32 program
w02.cpp A Simple Window
w03.cpp Handling Messages
w04.cpp Menus
w05.cpp Menus and Dialog
w06.cpp Modeless Dialogs
w07.cpp Standard Controls: Button, Edit, List Box
w08.cpp Changing Colours and Giving the Dialog an Icon
w09.cpp Creating controls at runtime
w10.cpp Using files and the common dialogs
w11.cpp Tool and Status barss
w12.cpp Multiple Document Interface
w13.cpp Bitmaps, Device Contexts and BitBlt
w14.cpp Transparent Bitmaps
w15.cpp Timers and Animation
w16.cpp Text and Fonts

[Basics:The simplest Win32 program]

win1.cpp

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, TEXT("こんにちは,Win32APIの世界にようこそ!!"), 
                    TEXT("The simplest Win32 program"), MB_OK);
    return 0;
}
[解説]
Buld→Runを実行すると 左のようなメッセージボックスが表示されます。これが一番かんたんなWindowsアプリでしょう。


[Basics:A Simple Window]

win2.cpp

#include <windows.h>

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, TEXT("Window Registration Failed!"),TEXT( "Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        TEXT("myWindowClass"),
        TEXT("The title of my window"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, TEXT("Window Creation Failed!"),TEXT("Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return (int)Msg.wParam;
}

[解説]
何もしませんが,一般的なウィンドウアプリケーションの機能を備えたプログラムです。大きさを変えたり,閉じたり出来るのを確認してください。 //Step 1でウィンドウクラスを登録しています。 //Step 2でウィンドウを作成しています。 //Step 3のところでメッセージループを実行しています。 //Step 4でメッセージの処理を指定しています。何もしないプログラムの雛形なのにウィンドウアプリケーションはこんな呪文のような長たらしいコードが 必要なのです。でも覚える必要なんかありません。この雛形をコピーして,いろいろと機能を書き足していけば良いだけですから。

[Basics:Handling Messages]

win3.cpp

#include <windows.h>

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_LBUTTONDOWN:{
            TCHAR szFileName[MAX_PATH];
            HINSTANCE hInstance = GetModuleHandle(NULL);
            GetModuleFileName(hInstance, szFileName, MAX_PATH);
            MessageBox(hwnd, szFileName, TEXT("This program is:"),
            MB_OK | MB_ICONINFORMATION);
        }
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
             PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;
    
    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
    
    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"),TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    
    // Step 3: The Message Loop
    while (GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return (int)Msg.wParam;
}

[解説]
case WM_LBUTTONDOWN: {.....}break;がLRESULT CALLBACK WndProc(...)文に付加されました。表示されるウィンドウは,一つ前のプログラムと 変わりませんが,マウスでウィンドウを右クリックすると左ような実行ファイル名をフルパスで表示したダイアログボックスが現れます。

[Basics:Menus]

win4.cpp

#include <windows.h>
#include "resource.h"

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg){
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm =  LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));

    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"),TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while (GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return (int)Msg.wParam;
}

resource.h
#define IDR_MYMENU               101
#define IDI_MYICON               201
#define IDM_EXIT                9001
#define IDM_ABOUT               9002
win4rc.rc
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...", IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"

[解説]
win4.cpp,resource.h,win4rc.rcの各ファイルとアイコンmy_icon.icoを同じフォルダーに用意します。 //Step 1:でwc.hIcon,wc.lpszMenuName,wc.hIconSmの三つにリソースからメイクするように指示しています。 このプログラムのメニューは、まだなんの動作もしません。

[Basics:Menus and Dialog]

win5.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam);

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam) {
    switch (msg) {
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                 case IDM_ABOUT:
                 {
                   int ret = (int)DialogBox(GetModuleHandle(NULL), 
                       MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
                   if(ret == -1)
                      MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
                                       MB_OK | MB_ICONINFORMATION);
                }
                break;
                case IDM_EXIT:
                    PostQuitMessage(0);
                break;
            }
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));


    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while (GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}

resource.h
#define IDR_MYMENU            101
#define IDI_MYICON            201
#define IDM_EXIT             9001
#define IDM_ABOUT            9002
#define IDD_ABOUT            9003
#define IDC_STATIC              3

win5rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X)",         IDM_EXIT
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...",              IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"

IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDI_MYICON,14,9,20,20
    LTEXT           "win5 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
一つ前のプログラムでは,メニューは動作しませんでしたが,このプログラムでは動作します。 メニューのファイル(&F)を開きバージョン情報(&A)をクリックすると左図のようにダイアログが開きます。また,ファイル(&F)を開き アプリケーションの終了(&X)でこのアプリケーションは終了します。 win5rc.rcには,一つ前のプログラムと違いがあります。#include <windows.h>の文が 入っているところです。ダイアログボックスの指定には,windows.hの中で定義されているので必要なのです。

[Basics:Modeless Dialogs]

win6.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK ToolDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam);
HWND g_hToolbar = NULL;

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam) {
    switch (msg) {
        case WM_CREATE:
            g_hToolbar = CreateDialog(GetModuleHandle(NULL), 
            MAKEINTRESOURCE(IDD_TOOLBAR),hwnd, ToolDlgProc);
             if(g_hToolbar != NULL)
            {
                ShowWindow(g_hToolbar, SW_SHOW);
            }
             else
            {
                MessageBox(hwnd, TEXT("CreateDialog returned NULL"),TEXT("Warning!"),  
                        MB_OK | MB_ICONINFORMATION);
             }
        break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case ID_DIALOG_SHOW:
                   ShowWindow(g_hToolbar, SW_SHOW);
                break;
                case ID_DIALOG_HIDE:
                    ShowWindow(g_hToolbar, SW_HIDE);
                 break;
                case IDM_EXIT:
                    DestroyWindow(g_hToolbar);
                    PostQuitMessage(0);
                break;
            }
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            DestroyWindow(g_hToolbar);
            PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));
    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL,TEXT("Window Registration Failed!"),TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0))
    {
        if(!IsDialogMessage(g_hToolbar, &Msg))
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK ToolDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam)
{
    switch(Message)
    {
        case WM_COMMAND:
            switch(LOWORD(wParam)){
                case IDC_PRESS:
                    MessageBox(hwnd,TEXT("Hi!"), TEXT("This is a message"), 
                        MB_OK | MB_ICONEXCLAMATION);
                break;
                case IDC_OTHER:
                    MessageBox(hwnd, TEXT("Bye!"), TEXT("This is also a message"), 
                        MB_OK | MB_ICONEXCLAMATION);
                break;
            }
        break;
        default:
            return FALSE;
    }
    return TRUE;
}

resource.h
#define IDR_MYMENU            101
#define IDI_MYICON            201
#define IDM_EXIT             9001
#define ID_DIALOG_SHOW       9002
#define ID_DIALOG_HIDE       9003
#define IDD_TOOLBAR          9004
#define IDC_PRESS            9005
#define IDC_OTHER            9006

win6rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
    END

    POPUP "ダイアログ(&D)"
    BEGIN
        MENUITEM "表\示(&S)", ID_DIALOG_SHOW
        MENUITEM  "非表\示(&H)",ID_DIALOG_HIDE
    END
END

IDI_MYICON ICON "my_icon.ico"

IDD_TOOLBAR DIALOGEX 0, 0, 98, 52
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "My Dialog Toolbar"
FONT 8, "MS Sans Serif"
BEGIN
    PUSHBUTTON      "このボタンを押して(&I)",IDC_PRESS,7,7,84,14
    PUSHBUTTON      "こっちも押して(&O)",IDC_OTHER,7,31,84,14
END

[解説]
Modeless Dialogなので,メインのウィンドウと同時に表示されます。 リソーススクリプトのWS_POPUPをWS_CHILDにするとメインウィンドウの中に 表示され外には出なくなります。

[Basics:Standard Controls: Button, Edit, List Box]

win7.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam) {
    switch (Message) {
        case WM_INITDIALOG:
            SetDlgItemText(hwnd, IDC_TEXT, TEXT("This is a string"));
            SetDlgItemInt(hwnd, IDC_NUMBER, 5, FALSE);
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
          case IDC_ADD: {
            BOOL bSuccess;
            int nTimes = GetDlgItemInt(hwnd, IDC_NUMBER, &bSuccess, FALSE);
            if (bSuccess) {
                int len = GetWindowTextLength(GetDlgItem(hwnd, IDC_TEXT));
                if (len > 0) {
                   int i;
                   TCHAR* buf;
                   buf = (TCHAR*)GlobalAlloc(GPTR, (len + 1)  * 2);
                   GetDlgItemText(hwnd, IDC_TEXT, buf, (len + 1) * 2);
                   for (i = 0;i < nTimes; i++) {
                       int index = (int)SendDlgItemMessage(hwnd, IDC_LIST,
                        LB_ADDSTRING, 0, (LPARAM)buf);
                        SendDlgItemMessage(hwnd, IDC_LIST,
                     LB_SETITEMDATA, (WPARAM)index, (LPARAM)nTimes);
                   }
                   GlobalFree((HANDLE)buf);
                   int count = (int)SendMessage(GetDlgItem(hwnd, IDC_LIST),
                   LB_GETCOUNT, 0, 0);
                   SetDlgItemInt(hwnd, IDC_SHOWCOUNT, count, FALSE);
                 } else {
                     MessageBox(hwnd, TEXT("You didn't enter anything!"),
                     TEXT("Warning"), MB_OK);
                        }
             } else {
                 MessageBox(hwnd, TEXT("Please enter a number!"), 
                 TEXT("Warning"), MB_OK);
             }                    
           }
            break;
          case IDC_REMOVE: {
              HWND hList = GetDlgItem(hwnd, IDC_LIST);
              int count = (int)SendMessage(hList, LB_GETSELCOUNT, 0, 0);
              if (count != LB_ERR) {
                  if (count != 0) {
                      int i;
                      int *buf = (int*)GlobalAlloc(GPTR, sizeof(int) * count);
                      SendMessage(hList, LB_GETSELITEMS, (WPARAM)count, (LPARAM)buf);
                      for (i = count - 1; i >= 0; i--) {
                          SendMessage(hList, LB_DELETESTRING, (WPARAM)buf[i], 0);
                      }
                      GlobalFree(buf);
                      count = (int)SendMessage(GetDlgItem(hwnd, IDC_LIST), 
                      LB_GETCOUNT, 0, 0);
                      SetDlgItemInt(hwnd, IDC_SHOWCOUNT, count, FALSE);
                  } else {
                        MessageBox(hwnd, TEXT("No items selected."), TEXT("Warning"), 
                        MB_OK);
                  }
              } 
          }
          break;
          case IDC_CLEAR:
            SendDlgItemMessage(hwnd, IDC_LIST, LB_RESETCONTENT, 0, 0);
            SetDlgItemInt(hwnd, IDC_SHOWCOUNT, 0, FALSE);
          break;
         }
         break;
         case WM_CLOSE:
         EndDialog(hwnd, 0);
         break;
         default:
         return FALSE;
    }
    return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    return (int)DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgProc);
}

resource.h
#define IDD_MAIN                        101
#define IDC_TEXT                       1000
#define IDC_NUMBER                     1001
#define IDC_LIST                       1002
#define IDC_ADD                        1003
#define IDC_CLEAR                      1004
#define IDC_REMOVE                     1005
#define IDC_SHOWCOUNT                  1006
#define IDC_STATIC                       -1

win7rc.rc
#include <windows.h>
#include "resource.h"

IDD_MAIN DIALOGEX DISCARDABLE  0, 0, 207, 156
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Controls One"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    PUSHBUTTON      "&Add",IDC_ADD,150,30,50,14
    PUSHBUTTON      "&Remove",IDC_REMOVE,150,47,50,14
    PUSHBUTTON      "&Clear",IDC_CLEAR,150,63,50,14
    EDITTEXT        IDC_TEXT,25,7,120,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_NUMBER,150,7,21,14,ES_NUMBER
    LISTBOX         IDC_LIST,7,25,138,106,LBS_NOINTEGRALHEIGHT | 
                    LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP
    LTEXT           "This item was added",IDC_STATIC,7,141,66,8
    LTEXT           "Add",IDC_STATIC,7,10,14,8
    LTEXT           "times.",IDC_STATIC,177,10,23,8
    CTEXT           "-",IDC_SHOWCOUNT,77,141,32,8
    LTEXT           "times",IDC_STATIC,114,141,17,8
END

[解説]
Edit BoxとList Box間でデータのやり取りをするダイアログだけのプログラムです。GetDlgItemInt(...),GetDlgItemText(...),SendMessage(...)を使って それぞれのコントロールからデータを取得したり,メッセージを送ることができます。左のダイアログは,Addボタンで上の段の左のEdit Boxの文を 左のEdit Boxに入れた数だけ,List Boxに書き込みます。RemoveボタンでList Boxで選択した文を削除します。 ClearボタンでList Bixのデータをすべてクリアします。 int len = (int) GetWindowTextLength(GetDlgItem(hwnd, IDC_TEXT));で取得した文の長さ+1の2倍のメモリーを用意しているのはUNICODE対応のためです。

[Basics:Dialog FAQ:Changing Colours and Giving the Dialog an Icon]

win8.cpp

#include <windows.h>
#include "resource.h"

HBRUSH g_hbrBackground = NULL;

BOOL CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam) {
    switch (Message) {
        case WM_INITDIALOG:
        g_hbrBackground = CreateSolidBrush(RGB(0, 0, 0));

        SendMessage(hwnd, WM_SETICON, ICON_SMALL, 
        (LPARAM)LoadIcon(GetModuleHandle(NULL),
                    MAKEINTRESOURCE(IDI_MYICON)));
        SendMessage(hwnd, WM_SETICON, ICON_BIG,
        (LPARAM)LoadIcon(GetModuleHandle(NULL),
                    MAKEINTRESOURCE(IDI_MYICON)));
        break;
        case WM_CLOSE:
        EndDialog(hwnd, 0);
        break;
        case WM_CTLCOLORDLG:
        return (LONG)g_hbrBackground;
        case WM_CTLCOLORSTATIC: {
            HDC hdcStatic = (HDC)wParam;
            SetTextColor(hdcStatic, RGB(255, 255, 255));
            SetBkMode(hdcStatic, TRANSPARENT);
            return (LONG)g_hbrBackground;
        }
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, 0);
            break;
        }
        break;
        case WM_DESTROY:
        DeleteObject(g_hbrBackground);
        break;
        default:
        return FALSE;
    }
    return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    return (int)DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgProc);
}


resource.h
#define IDD_MAIN                       101
#define IDI_MYICON                    9000
#define IDC_STATIC                      -1

win8rc.rc
#include <windows.h>
#include "resource.h"

IDD_MAIN DIALOG DISCARDABLE  0, 0, 186, 46
STYLE DS_MODALFRAME | WS_POPUP | DS_CENTER |  WS_CAPTION | WS_SYSMENU
CAPTION "Dialog tricks"
FONT 8, "MS Sans Serif"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,129,7,50,14
    LTEXT           "Hi there.",IDC_STATIC,43,16,28,8
END

IDI_MYICON ICON "my_icon.ico"


[解説]
コントロールは,デフォルトで灰色の背景と黒文字です。このダイアログは,WM_CTLCOLORDLGとWM_CTLCOLORSTATICの 部分で背景を黒に文字を白に 変えて表示しています。また,WM_INITDIALOGでダイアログのバーにアイコンを表示しています。

[App Part 1: Creating controls at runtime]

win9.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM
wParam, LPARAM lParam);

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam) {
    switch (msg) {
    case WM_COMMAND:
    switch (LOWORD(wParam)) {
    case IDM_ABOUT:
    {
    int ret = (int)DialogBox(GetModuleHandle(NULL), 
    MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
    if(ret == -1)
    MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
    MB_OK | MB_ICONINFORMATION);
    }
    break;
    case IDM_EXIT:
    PostQuitMessage(0);
    break;
    }
    break;
    case WM_CREATE:
    {
    HFONT hfDefault;
    HWND hEdit;
    hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""), 
    WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL
    | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 
    0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
    if(hEdit == NULL)
    MessageBox(hwnd, TEXT("Could not create edit box."), TEXT("Error"), 
    MB_OK | MB_ICONERROR);
    hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
    SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
    }
    break;
    case WM_SIZE:{
    HWND hEdit;
    RECT rcClient;
    GetClientRect(hwnd, &rcClient);
    hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
    SetWindowPos(hEdit, NULL, 0, 0, rcClient.right,
    rcClient.bottom, SWP_NOZORDER);
    }
    break;
    case WM_CLOSE:
    DestroyWindow(hwnd);
    break;
    case WM_DESTROY:
    PostQuitMessage(0);
    break;
    default:
    return DefWindowProc(hwnd, msg, wParam, lParam);
    }
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));


    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

// Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 480, 320,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while (GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message,
WPARAM wParam, LPARAM lParam) {
    switch (Message) {
    case WM_COMMAND:
    switch (LOWORD(wParam)) {
    case IDOK:
    EndDialog(hwnd, IDOK);
    break;}
    break;
    default:
    return FALSE;
    }
return TRUE;
}

resource.h
#define IDR_MYMENU          101
#define IDI_MYICON          201
#define IDC_MYICON          201
#define IDM_EXIT           9001
#define IDM_ABOUT          9002
#define IDD_ABOUT          9003
#define IDC_STATIC           -1
#define IDC_MAIN_EDIT       102

win9rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X)",             IDM_EXIT
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...",              IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"

IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win9 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
WM_CREATEでエディットコントロールを作成し,WM_SIZEでクライアント領域にフィットさせています。 文章を表示できますが,テキストファイルの読み込みや保存はまだできません。このプログラムを元に 機能を追加していき,マルチウィンドウのテキストエディタを作成していきます。

[App Part 2: Using files and the common dialogs]

win10.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam);

BOOL LoadTextFileToEdit(HWND hEdit, LPCTSTR pszFileName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;

    hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, 0, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwFileSize;

        dwFileSize = GetFileSize(hFile, NULL);
        if (dwFileSize != 0xFFFFFFFF) {
            LPSTR pszFileText;
            pszFileText = (LPSTR)GlobalAlloc(GPTR, (dwFileSize + 1) * 2);
            if (pszFileText != NULL) {
                DWORD dwRead;

                if (ReadFile(hFile, pszFileText, dwFileSize, &dwRead, NULL)) {
                    pszFileText[dwFileSize] = 0; // Add null terminator
                    if (SetWindowTextA(hEdit, (LPCSTR)pszFileText))
                        bSuccess = TRUE; // It worked!
                }
                GlobalFree(pszFileText);
            }
        }
        CloseHandle(hFile);
    }
    return bSuccess;
}

BOOL SaveTextFileFromEdit(HWND hEdit, LPCTSTR pszFileName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;

    hFile = CreateFile(pszFileName, GENERIC_WRITE, 0, NULL,
                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwTextLength;

        dwTextLength = GetWindowTextLength(hEdit);
        // No need to bother if there's no text.
        if (dwTextLength > 0) {
            LPSTR pszText;
            DWORD dwBufferSize = (dwTextLength + 1) * 2;

            pszText = (LPSTR)GlobalAlloc(GPTR, dwBufferSize);
            if (pszText != NULL) {
                if (GetWindowTextA(hEdit, (LPSTR)pszText, dwBufferSize)) {
                    DWORD dwWritten;

                    if (WriteFile(hFile, pszText, dwBufferSize, &dwWritten, NULL))
                        bSuccess = TRUE;
                }
                GlobalFree(pszText);
            }
        }
        CloseHandle(hFile);
    }
    return bSuccess;
}

void DoFileOpen(HWND hwnd) {
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH] = TEXT("");

    ZeroMemory(&ofn, sizeof(ofn));

    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
    ofn.lpstrDefExt = TEXT("txt");

    if (GetOpenFileName(&ofn)) {
        HWND hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
        LoadTextFileToEdit(hEdit, szFileName);
    }
}

void DoFileSave(HWND hwnd) {
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH] = TEXT("");

    ZeroMemory(&ofn, sizeof(ofn));

    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrDefExt = TEXT("txt");
    ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY
    | OFN_OVERWRITEPROMPT;

    if (GetSaveFileName(&ofn)) {
        HWND hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
        SaveTextFileFromEdit(hEdit, szFileName);
    }
}

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam) {
    switch (msg) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case ID_FILE_NEW:
            SetDlgItemText(hwnd, IDC_MAIN_EDIT, TEXT(""));
            break;
            case ID_FILE_OPEN:
            DoFileOpen(hwnd);
            break;
            case ID_FILE_SAVEAS:
            DoFileSave(hwnd);
            break;
            case IDM_ABOUT: {
            int ret = (int)DialogBox(GetModuleHandle(NULL),
            MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
            if (ret == -1)
            MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
            MB_OK | MB_ICONINFORMATION);
            }
            break;
            case IDM_EXIT:
            PostQuitMessage(0);
            break;
        }
        break;
        case WM_CREATE: {
            HFONT hfDefault;
            HWND hEdit;
            hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""),
                        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL
                        | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
                        0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT,
                        GetModuleHandle(NULL), NULL);
            if (hEdit == NULL)
                MessageBox(hwnd, TEXT("Could not create edit box."), TEXT("Error"),
                           MB_OK | MB_ICONERROR);
            hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
            SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault,
            MAKELPARAM(FALSE, 0));
        }
        break;
        case WM_SIZE: {
            HWND hEdit;
            RECT rcClient;
            GetClientRect(hwnd, &rcClient);
            hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
            SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, 
            SWP_NOZORDER);
        }
        break;
        case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
        PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));


    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 480, 320,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while (GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}

resource.h
#define IDR_MYMENU        101
#define IDI_MYICON        201
#define IDC_MYICON        202
#define IDM_EXIT         9001
#define IDM_ABOUT        9002
#define IDD_ABOUT        9003
#define IDC_STATIC         -1
#define IDC_MAIN_EDIT     102
#define ID_FILE_NEW      8001
#define ID_FILE_OPEN     8002
#define ID_FILE_SAVEAS   8003

win10rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "新規ファイル(&N)",             ID_FILE_NEW
        MENUITEM "開く(&O)...",                  ID_FILE_OPEN
        MENUITEM "保存(&A)...",                  ID_FILE_SAVEAS
        MENUITEM SEPARATOR
        MENUITEM "アプリケーションの終了(&X)",   IDM_EXIT
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...",        IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"

IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win10 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
コモンダイアログからテキストファイルの読み込みと書き込み機能を付加しました。 DWORD dwBufferSize = (dwTextLength + 1) * 2;でバッファーサイズを2倍とっているのは UNICODEに対応させているためです。

[App Part 3: Tool and Status barss]

win11.cpp

#include <windows.h>
#include <commctrl.h>
#include "resource.h"

//MinGW,Link C:\MinGW\lib\libcomctl32.a
//Visual C++ 2005,Delete comment out the next line.
//#pragma comment(lib, "comctl32.lib")

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam);

BOOL LoadTextFileToEdit(HWND hEdit, LPCTSTR pszFileName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;

    hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, 0, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwFileSize;

        dwFileSize = GetFileSize(hFile, NULL);
        if (dwFileSize != 0xFFFFFFFF) {
            LPSTR pszFileText;
            pszFileText = (LPSTR)GlobalAlloc(GPTR, (dwFileSize + 1) * 2);
            if (pszFileText != NULL) {
                DWORD dwRead;

                if (ReadFile(hFile, pszFileText, dwFileSize, &dwRead;, NULL)) {
                    pszFileText[dwFileSize] = 0; // Add null terminator
                    if (SetWindowTextA(hEdit, (LPCSTR)pszFileText))
                        bSuccess = TRUE; // It worked!
                }
                GlobalFree(pszFileText);
            }
        }
        CloseHandle(hFile);
    }
    return bSuccess;
}

BOOL SaveTextFileFromEdit(HWND hEdit, LPCTSTR pszFileName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;

    hFile = CreateFile(pszFileName, GENERIC_WRITE, 0, NULL,
                       CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwTextLength;

        dwTextLength = GetWindowTextLength(hEdit);
        // No need to bother if there's no text.
        if (dwTextLength > 0) {
            LPSTR pszText;
            DWORD dwBufferSize = (dwTextLength + 1) * 2;

            pszText = (LPSTR)GlobalAlloc(GPTR, dwBufferSize);
            if (pszText != NULL) {
                if (GetWindowTextA(hEdit, (LPSTR)pszText, dwBufferSize)) {
                    DWORD dwWritten;

                    if (WriteFile(hFile, pszText, dwBufferSize, &dwWritten;, NULL))
                        bSuccess = TRUE;
                }
                GlobalFree(pszText);
            }
        }
        CloseHandle(hFile);
    }
    return bSuccess;
}

void DoFileOpen(HWND hwnd) {
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH] = TEXT("");

    ZeroMemory(&ofn;, sizeof(ofn));

    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
    ofn.lpstrDefExt = TEXT("txt");

    if (GetOpenFileName(&ofn;)) {
        HWND hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
        if (LoadTextFileToEdit(hEdit, szFileName)) {
            SendDlgItemMessage(hwnd, IDC_MAIN_STATUS, SB_SETTEXT, 0,
            (LPARAM)TEXT("Opened..."));
            SendDlgItemMessage(hwnd, IDC_MAIN_STATUS, SB_SETTEXT, 1,
            (LPARAM)szFileName);
        }
    }
}

void DoFileSave(HWND hwnd) {
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH] = TEXT("");

    ZeroMemory(&ofn;, sizeof(ofn));

    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrDefExt = TEXT("txt");
    ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | 
    OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;

    if (GetSaveFileName(&ofn;)) {
        HWND hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
        if (SaveTextFileFromEdit(hEdit, szFileName)) {
            SendDlgItemMessage(hwnd, IDC_MAIN_STATUS, SB_SETTEXT, 0, 
            (LPARAM)TEXT("Saved..."));
            SendDlgItemMessage(hwnd, IDC_MAIN_STATUS, SB_SETTEXT, 1,
            (LPARAM)szFileName);
        }
    }
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            HFONT hfDefault;
            HWND hEdit;

            HWND hTool;
            TBBUTTON tbb[3];
            TBADDBITMAP tbab;

            HWND hStatus;
            int statwidths[] = {100, -1};

            // Create Edit Control
            hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""),
                         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL
                                  | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
                         0, 0, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT,
                         GetModuleHandle(NULL), NULL);
            if (hEdit == NULL)
                MessageBox(hwnd, TEXT("Could not create edit box."),
                           TEXT("Error"), MB_OK | MB_ICONERROR);

            hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
            SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));

            // Create Toolbar

            hTool = CreateWindowEx(0, TOOLBARCLASSNAME, 
                                   NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
                                   hwnd, (HMENU)IDC_MAIN_TOOL,
                                   GetModuleHandle(NULL), NULL);
            if (hTool == NULL)
                MessageBox(hwnd, TEXT("Could not create tool bar."),
                           TEXT("Error"), MB_OK | MB_ICONERROR);

            // Send the TB_BUTTONSTRUCTSIZE message, which is required for
            // backward compatibility.
            SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);

            tbab.hInst = HINST_COMMCTRL;
            tbab.nID = IDB_STD_SMALL_COLOR;
            SendMessage(hTool, TB_ADDBITMAP, 0, (LPARAM)&tbab;);

            ZeroMemory(tbb, sizeof(tbb));
            tbb[0].iBitmap = STD_FILENEW;
            tbb[0].fsState = TBSTATE_ENABLED;
            tbb[0].fsStyle = TBSTYLE_BUTTON;
            tbb[0].idCommand = ID_FILE_NEW;

            tbb[1].iBitmap = STD_FILEOPEN;
            tbb[1].fsState = TBSTATE_ENABLED;
            tbb[1].fsStyle = TBSTYLE_BUTTON;
            tbb[1].idCommand = ID_FILE_OPEN;

            tbb[2].iBitmap = STD_FILESAVE;
            tbb[2].fsState = TBSTATE_ENABLED;
            tbb[2].fsStyle = TBSTYLE_BUTTON;
            tbb[2].idCommand = ID_FILE_SAVEAS;

            SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb) / sizeof(TBBUTTON),
            (LPARAM)&tbb;);

            // Create Status bar

            hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL,
                        WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0,
                        hwnd, (HMENU)IDC_MAIN_STATUS, GetModuleHandle(NULL), NULL);

            SendMessage(hStatus, SB_SETPARTS, sizeof(statwidths) / sizeof(int),
            (LPARAM)statwidths);
            SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)TEXT("Hi there :"));
        }
        break;
        case WM_SIZE: {
            HWND hTool;
            RECT rcTool;
            int iToolHeight;

            HWND hStatus;
            RECT rcStatus;
            int iStatusHeight;

            HWND hEdit;
            int iEditHeight;
            RECT rcClient;

            // Size toolbar and get height

            hTool = GetDlgItem(hwnd, IDC_MAIN_TOOL);
            SendMessage(hTool, TB_AUTOSIZE, 0, 0);

            GetWindowRect(hTool, &rcTool;);
            iToolHeight = rcTool.bottom - rcTool.top;

            // Size status bar and get height

            hStatus = GetDlgItem(hwnd, IDC_MAIN_STATUS);
            SendMessage(hStatus, WM_SIZE, 0, 0);

            GetWindowRect(hStatus, &rcStatus;);
            iStatusHeight = rcStatus.bottom - rcStatus.top;

            // Calculate remaining height and size edit

            GetClientRect(hwnd, &rcClient;);

            iEditHeight = rcClient.bottom - iToolHeight - iStatusHeight;

            hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
            SetWindowPos(hEdit, NULL, 0, iToolHeight, rcClient.right, 
                                             iEditHeight, SWP_NOZORDER);
        }
        break;
        case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
        PostQuitMessage(0);
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case ID_FILE_NEW:
            SetDlgItemText(hwnd, IDC_MAIN_EDIT, TEXT(""));
            break;
            case ID_FILE_OPEN:
            DoFileOpen(hwnd);
            break;
            case ID_FILE_SAVEAS:
            DoFileSave(hwnd);
            break;
            case IDM_ABOUT: {
                int ret = (int)DialogBox(GetModuleHandle(NULL),
                                         MAKEINTRESOURCE(IDD_ABOUT), hwnd, 
                                         AboutDlgProc);
                if (ret == -1)
                    MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
                               MB_OK | MB_ICONINFORMATION);
            }
            break;
            case IDM_EXIT:
            PostQuitMessage(0);
            break;
        }
        break;
        default:
        return (int)DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    InitCommonControls();

    wc.cbSize	= sizeof(WNDCLASSEX);
    wc.style	= 0;
    wc.lpfnWndProc	= WndProc;
    wc.cbClsExtra	= 0;
    wc.cbWndExtra	= 0;
    wc.hInstance	= hInstance;
    wc.hIcon	= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor	= LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm	= LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));

    if (!RegisterClassEx(&wc;)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), 
                           TEXT("Error!"),MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(
               0,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
               CW_USEDEFAULT, CW_USEDEFAULT, 480, 320,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg;, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg;);
        DispatchMessage(&Msg;);
    }
    return (int)Msg.wParam;
}


BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}

resource.h
#define IDR_MYMENU                 100
#define IDM_EXIT                 40001
#define ID_FILE_OPEN             40002
#define ID_FILE_SAVEAS           40003
#define ID_FILE_NEW              40004
#define IDC_MAIN_EDIT              101
#define IDC_MAIN_TOOL              102
#define IDC_MAIN_STATUS            103
#define IDI_MYICON                 201
#define IDC_MYICON                 202
#define IDM_ABOUT                 9002
#define IDD_ABOUT                 9003
#define IDC_STATIC                  -1

win11rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU DISCARDABLE 
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "新規ファイル(&N)",         ID_FILE_NEW
        MENUITEM "開く(&O)...",                  ID_FILE_OPEN
        MENUITEM "保存 (&A)...",                 ID_FILE_SAVEAS
        MENUITEM SEPARATOR
        MENUITEM "終了(&X)",                     IDM_EXIT
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...",     IDM_ABOUT
    END
END


IDI_MYICON ICON "my_icon.ico"

IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win11 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
ツールバーとステイタスバーを付加しました。 #include <commctrl.h>が必要です。

[App Part 4: Multiple Document Interface]

win12.cpp

#include <windows.h>
#include <commctrl.h>
#include "resource.h"
//MinGW,Link C:\MinGW\lib\libcomctl32.a
//Visual C++ 2005,Delete comment out the next line.
//#pragma comment(lib, "comctl32.lib")

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam);

HWND g_hMDIClient = NULL;
HWND g_hMainWindow = NULL;

BOOL LoadTextFileToEdit(HWND hEdit, LPCTSTR pszFileName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;

    hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, 0, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
        DWORD dwFileSize;

        dwFileSize = GetFileSize(hFile, NULL);
        if (dwFileSize != 0xFFFFFFFF) {
            LPSTR pszFileText;

            pszFileText = (LPSTR)GlobalAlloc(GPTR, (dwFileSize + 1) * 2);
            if (pszFileText != NULL) {
                DWORD dwRead;

                if (ReadFile(hFile, pszFileText, dwFileSize, &dwRead, NULL))
                {
                    pszFileText[dwFileSize] = 0; // Add null terminator
                    if (SetWindowTextA(hEdit, pszFileText))
                        bSuccess = TRUE; // It worked!
                }
                GlobalFree(pszFileText);
            }
        }
        CloseHandle(hFile);
    }
    return bSuccess;
}

BOOL SaveTextFileFromEdit(HWND hEdit, LPCTSTR pszFileName) {
    HANDLE hFile;
    BOOL bSuccess = FALSE;
    hFile = CreateFile(pszFileName, GENERIC_WRITE, 0, NULL,
    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != INVALID_HANDLE_VALUE) {
    DWORD dwTextLength;
    dwTextLength = GetWindowTextLength(hEdit);
    // No need to bother if there's no text.
    if (dwTextLength > 0) {
    LPSTR pszText;
    DWORD dwBufferSize = (dwTextLength + 1) * 2;
    pszText = (LPSTR)GlobalAlloc(GPTR, dwBufferSize);
    if (pszText != NULL) {
    if (GetWindowTextA(hEdit, pszText, dwBufferSize)) {
    DWORD dwWritten;
		if (WriteFile(hFile, pszText, dwTextLength, &dwWritten;, NULL))
    bSuccess = TRUE;
    }
    GlobalFree(pszText);
    }
    }
    CloseHandle(hFile);
	}
return bSuccess;
}

void DoFileOpen(HWND hwnd) {
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH] = TEXT("");

    ZeroMemory(&ofn;, sizeof(ofn));

    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFilter = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
    ofn.lpstrDefExt = TEXT("txt");

    if (GetOpenFileName(&ofn;)) {
    HWND hEdit = GetDlgItem(hwnd, IDC_CHILD_EDIT);
    if (LoadTextFileToEdit(hEdit, szFileName)) {
    SendDlgItemMessage(g_hMainWindow, IDC_MAIN_STATUS, SB_SETTEXT, 0,
    (LPARAM)TEXT("Opened..."));
    SendDlgItemMessage(g_hMainWindow, IDC_MAIN_STATUS, SB_SETTEXT, 1,
    (LPARAM)szFileName);
    SetWindowText(hwnd, szFileName);
    }
	}
}

void DoFileSave(HWND hwnd) {
    OPENFILENAME ofn;
    TCHAR szFileName[MAX_PATH] = TEXT("");
    ZeroMemory(&ofn;, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFilter 
    = TEXT("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0");
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrDefExt = TEXT("txt");
    ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY
    | OFN_OVERWRITEPROMPT;

    if (GetSaveFileName(&ofn;)) {
    HWND hEdit = GetDlgItem(hwnd, IDC_CHILD_EDIT);
    if (SaveTextFileFromEdit(hEdit, szFileName)) {
    SendDlgItemMessage(g_hMainWindow, IDC_MAIN_STATUS, SB_SETTEXT, 0,
    (LPARAM)TEXT("Saved..."));
    SendDlgItemMessage(g_hMainWindow, IDC_MAIN_STATUS, SB_SETTEXT, 1,
    (LPARAM)szFileName);
    SetWindowText(hwnd, szFileName);
    }
	}
}

HWND CreateNewMDIChild(HWND hMDIClient) {
    MDICREATESTRUCT mcs;
    HWND hChild;

    mcs.szTitle = TEXT("[Untitled]");
    mcs.szClass = TEXT("myMDIChildWindowsClass");
    mcs.hOwner = GetModuleHandle(NULL);
    mcs.x = mcs.cx = CW_USEDEFAULT;
    mcs.y = mcs.cy = CW_USEDEFAULT;
    mcs.style = MDIS_ALLCHILDSTYLES;

    hChild = (HWND)SendMessage(hMDIClient, WM_MDICREATE, 0, (LONG) & mcs);
    if (!hChild) {
    MessageBox(hMDIClient, TEXT("MDI Child creation failed."), 
    TEXT("Oh Oh..."), MB_ICONEXCLAMATION | MB_OK);
    }
    return hChild;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
        HWND hTool;
        TBBUTTON tbb[3];
        TBADDBITMAP tbab;
        HWND hStatus;
        int statwidths[] = {100, -1};


				CLIENTCREATESTRUCT ccs;
				// Create MDI Client
        // Find window menu where children will be listed
        ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 2);
        ccs.idFirstChild = ID_MDI_FIRSTCHILD;
        g_hMDIClient = CreateWindowEx(WS_EX_CLIENTEDGE, 
        TEXT("mdiclient"), NULL,
        WS_CHILD | WS_CLIPCHILDREN | 
        WS_VSCROLL | WS_HSCROLL
        | WS_VISIBLE, CW_USEDEFAULT, 
        CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
        hwnd, (HMENU)IDC_MAIN_MDI, 
        GetModuleHandle(NULL), (LPVOID) & ccs);
        if (g_hMDIClient == NULL)
        MessageBox(hwnd, TEXT("Could not create MDI client."), 
        TEXT("Error"),MB_OK | MB_ICONERROR);
        // Create Toolbar
        hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
        WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
        hwnd, (HMENU)IDC_MAIN_TOOL, 
        GetModuleHandle(NULL), NULL);
        if (hTool == NULL)
        MessageBox(hwnd, TEXT("Could not create tool bar."), TEXT("Error"),
        MB_OK | MB_ICONERROR);
        // Send the TB_BUTTONSTRUCTSIZE message, which is required for
        // backward compatibility.
        SendMessage(hTool, TB_BUTTONSTRUCTSIZE,
        (WPARAM)sizeof(TBBUTTON), 0);
        tbab.hInst = HINST_COMMCTRL;
        tbab.nID = IDB_STD_SMALL_COLOR;
        SendMessage(hTool, TB_ADDBITMAP, 0, (LPARAM)&tbab);
        ZeroMemory(tbb, sizeof(tbb));
        tbb[0].iBitmap = STD_FILENEW;
        tbb[0].fsState = TBSTATE_ENABLED;
        tbb[0].fsStyle = TBSTYLE_BUTTON;
        tbb[0].idCommand = ID_FILE_NEW;
        tbb[1].iBitmap = STD_FILEOPEN;
        tbb[1].fsState = TBSTATE_ENABLED;
        tbb[1].fsStyle = TBSTYLE_BUTTON;
        tbb[1].idCommand = ID_FILE_OPEN;
        tbb[2].iBitmap = STD_FILESAVE;
        tbb[2].fsState = TBSTATE_ENABLED;
        tbb[2].fsStyle = TBSTYLE_BUTTON;
        tbb[2].idCommand = ID_FILE_SAVEAS;
        SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb) / sizeof(TBBUTTON),
        (LPARAM)&tbb;);
        // Create Status bar
        hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL,
        WS_CHILD | WS_VISIBLE | 
        SBARS_SIZEGRIP, 0, 0, 0, 0,
        hwnd, (HMENU)IDC_MAIN_STATUS,
        GetModuleHandle(NULL), NULL);
        SendMessage(hStatus, SB_SETPARTS, sizeof(statwidths) / sizeof(int),
        (LPARAM)statwidths);
        SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)TEXT("Hi there :"));}
        break;
        case WM_SIZE: {
        HWND hTool;
        RECT rcTool;
        int iToolHeight;
        HWND hStatus;
        RECT rcStatus;
        int iStatusHeight;
        HWND hMDI;
        int iMDIHeight;
        RECT rcClient;
        // Size toolbar and get height
        hTool = GetDlgItem(hwnd, IDC_MAIN_TOOL);
        SendMessage(hTool, TB_AUTOSIZE, 0, 0);
        GetWindowRect(hTool, &rcTool;);
        iToolHeight = rcTool.bottom - rcTool.top;
        // Size status bar and get height
        hStatus = GetDlgItem(hwnd, IDC_MAIN_STATUS);
        SendMessage(hStatus, WM_SIZE, 0, 0);
        GetWindowRect(hStatus, &rcStatus;);
        iStatusHeight = rcStatus.bottom - rcStatus.top;
        // Calculate remaining height and size edit
        GetClientRect(hwnd, &rcClient;);
        iMDIHeight = rcClient.bottom - iToolHeight - iStatusHeight;
        hMDI = GetDlgItem(hwnd, IDC_MAIN_MDI);
        SetWindowPos(hMDI, NULL, 0, iToolHeight, rcClient.right,
        iMDIHeight, SWP_NOZORDER);
        }
        break;
        case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
        PostQuitMessage(0);
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
        break;
        case ID_FILE_NEW:
        CreateNewMDIChild(g_hMDIClient);
        break;
        case ID_FILE_OPEN: {
        HWND hChild = CreateNewMDIChild(g_hMDIClient);
        if (hChild) {
        DoFileOpen(hChild);}
        }
        break;
        case ID_FILE_CLOSE: {
        HWND hChild = (HWND)SendMessage(g_hMDIClient, WM_MDIGETACTIVE, 0, 0);
        if (hChild) {
        SendMessage(hChild, WM_CLOSE, 0, 0);}
        }
        break;
        case ID_WINDOW_TILE:
        SendMessage(g_hMDIClient, WM_MDITILE, 0, 0);
        break;
        case ID_WINDOW_CASCADE:
        SendMessage(g_hMDIClient, WM_MDICASCADE, 0, 0);
        break;
        case IDM_ABOUT: {
        int ret = (int)DialogBox(GetModuleHandle(NULL),
        MAKEINTRESOURCE(IDD_ABOUT),hwnd, AboutDlgProc);
        if (ret == -1)
        MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
        MB_OK | MB_ICONINFORMATION);
        }
        break;
        case IDM_EXIT:
        PostQuitMessage(0);
        break;
            // Handle MDI Window commands
				default: {
        if (LOWORD(wParam) >= ID_MDI_FIRSTCHILD) {
        DefFrameProc(hwnd, g_hMDIClient, WM_COMMAND, wParam, lParam);}
        else {HWND hChild = (HWND)SendMessage(g_hMDIClient,WM_MDIGETACTIVE, 0, 0);
        if (hChild) {
        SendMessage(hChild, WM_COMMAND, wParam, lParam);
        }
        }
        }
				}
        break;
	default:
  return DefFrameProc(hwnd, g_hMDIClient, msg, wParam, lParam);
    }
    return 0;
}

LRESULT CALLBACK MDIChildWndProc(HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
        HFONT hfDefault;
        HWND hEdit;
            // Create Edit Control
        hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT(""),
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL
        | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
        0, 0, 100, 100, hwnd, (HMENU)IDC_CHILD_EDIT, 
        GetModuleHandle(NULL), NULL);
        if (hEdit == NULL)
        MessageBox(hwnd, TEXT("Could not create edit box."), TEXT("Error"),
        MB_OK | MB_ICONERROR);
        hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
        SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
        }
        break;
        case WM_MDIACTIVATE: {
        HMENU hMenu, hFileMenu;
        UINT EnableFlag;
        hMenu = GetMenu(g_hMainWindow);
        if (hwnd == (HWND)lParam) {	   //being activated, enable the menus
        EnableFlag = MF_ENABLED;}
        else {	//being de-activated, gray the menus
                EnableFlag = MF_GRAYED;
        }
        EnableMenuItem(hMenu, 1, MF_BYPOSITION | EnableFlag);
        EnableMenuItem(hMenu, 2, MF_BYPOSITION | EnableFlag);
        hFileMenu = GetSubMenu(hMenu, 0);
        EnableMenuItem(hFileMenu, ID_FILE_SAVEAS, MF_BYCOMMAND | EnableFlag);
        EnableMenuItem(hFileMenu, ID_FILE_CLOSE, MF_BYCOMMAND | EnableFlag);
        EnableMenuItem(hFileMenu, ID_FILE_CLOSEALL, MF_BYCOMMAND | EnableFlag);
        DrawMenuBar(g_hMainWindow);
        }
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case ID_FILE_OPEN:
        DoFileOpen(hwnd);
        break;
        case ID_FILE_SAVEAS:
        DoFileSave(hwnd);
        break;
        case ID_EDIT_CUT:
        SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_CUT, 0, 0);
        break;
        case ID_EDIT_COPY:
        SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_COPY, 0, 0);
        break;
        case ID_EDIT_PASTE:
        SendDlgItemMessage(hwnd, IDC_CHILD_EDIT, WM_PASTE, 0, 0);
        break;
        }
        break;
        case WM_SIZE: {
        HWND hEdit;
        RECT rcClient;
        // Calculate remaining height and size edit
        GetClientRect(hwnd, &rcClient;);
        hEdit = GetDlgItem(hwnd, IDC_CHILD_EDIT);
        SetWindowPos(hEdit, NULL, 0, 0, rcClient.right,
        rcClient.bottom, SWP_NOZORDER);}
        return DefMDIChildProc(hwnd, msg, wParam, lParam);
        default:
        return DefMDIChildProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

BOOL SetUpMDIChildWindowClass(HINSTANCE hInstance) {
    WNDCLASSEX wc;
    wc.cbSize	= sizeof(WNDCLASSEX);
    wc.style	= CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc	= MDIChildWndProc;
    wc.cbClsExtra	= 0;
    wc.cbWndExtra	= 0;
    wc.hInstance	= hInstance;
    wc.hIcon	= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CMYICON));
    wc.hCursor	= LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = TEXT("myMDIChildWindowsClass");
    wc.hIconSm	= LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_CMYICON));

    if (!RegisterClassEx(&wc;)) {
        MessageBox(0, TEXT("Could Not Register Child Window"), 
        TEXT("Oh Oh..."), MB_ICONEXCLAMATION | MB_OK);
        return FALSE;
    } else
        return TRUE;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    InitCommonControls();

    wc.cbSize	= sizeof(WNDCLASSEX);
    wc.style	= 0;
    wc.lpfnWndProc	= WndProc;
    wc.cbClsExtra	= 0;
    wc.cbWndExtra	= 0;
    wc.hInstance	= hInstance;
    wc.hIcon	= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor	= LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowsClass");
    wc.hIconSm	= LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));

    if (!RegisterClassEx(&wc;)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    if (!SetUpMDIChildWindowClass(hInstance))
        return 0;

    hwnd = CreateWindowEx(
               0,
               TEXT("myWindowsClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
               CW_USEDEFAULT, CW_USEDEFAULT, 480, 320,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    g_hMainWindow = hwnd;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg;, NULL, 0, 0) > 0) {
        if (!TranslateMDISysAccel(g_hMDIClient, &Msg;)) {
            TranslateMessage(&Msg;);
            DispatchMessage(&Msg;);
        }
    }
    return (int)Msg.wParam;
}


BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}

resource.h
#define IDR_MYMENU                        100
#define IDM_EXIT                          200
#define IDI_MYICON                        201
#define IDC_MYICON                        202
#define IDI_CMYICON                       203
#define IDM_ABOUT                        9002
#define IDD_ABOUT                        9003
#define IDC_STATIC                         -1
#define ID_FILE_NEW                     40002
#define ID_FILE_OPEN                    40003
#define ID_FILE_SAVEAS                  40005
#define ID_WINDOW_CASCADE               40008
#define ID_WINDOW_TILE                  40009
#define ID_FILE_CLOSE                   40010
#define ID_FILE_CLOSEALL                40011
#define ID_EDIT_CUT                     40015
#define ID_EDIT_COPY                    40016
#define ID_EDIT_PASTE                   40017
#define IDC_MAIN_MDI                      101
#define IDC_MAIN_TOOL                     102
#define IDC_MAIN_STATUS                   103
#define IDC_CHILD_EDIT                    104
#define IDC_MAIN_EDIT                     105
#define ID_MDI_FIRSTCHILD               50000
win12rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU DISCARDABLE 
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "新規ファイル(&N)",           ID_FILE_NEW
        MENUITEM "開く(&O)...",                ID_FILE_OPEN
        MENUITEM "保存(&A)...",                ID_FILE_SAVEAS, GRAYED
        MENUITEM SEPARATOR
        MENUITEM "閉じる(&C)",                 ID_FILE_CLOSE, GRAYED
        MENUITEM SEPARATOR
        MENUITEM "終了(&X)",                   IDM_EXIT
    END
    POPUP "編集(&E)", GRAYED
    BEGIN
        MENUITEM "カット(&U)",                 ID_EDIT_CUT
        MENUITEM "コピー(&C)",                 ID_EDIT_COPY
        MENUITEM "ペースト(&P)",               ID_EDIT_PASTE
    END
    POPUP "ウィンドウ(&W)", GRAYED
    BEGIN
        MENUITEM "並べて表\示(&T)",                 ID_WINDOW_TILE
        MENUITEM "重ねて表\示(&C)",                 ID_WINDOW_CASCADE
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報(&A)...",       IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"
IDI_CMYICON ICON "icon9.ico"

IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win12 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
ずいぶんと長いソースになっていますが,子ウィンドウの作成もメインの ウィンドウも作成法は同じであることが 分かりと思います。マルチウィンドウのテキストエディタがこれで完成です。

[Bitmaps, Device Contexts and BitBlt]

win13.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam);
HBITMAP g_hbmBall = NULL;

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, 
		LPARAM lParam) {
    switch (msg) {
        case WM_CREATE:
             g_hbmBall = LoadBitmap(GetModuleHandle(NULL), 
             MAKEINTRESOURCE(IDB_BALL));
        if(g_hbmBall == NULL)
            MessageBox(hwnd, TEXT("Could not load IDB_BALL!"), TEXT("Error"), 
                                                  MB_OK | MB_ICONEXCLAMATION);
        break;
        case WM_PAINT:
            {
            BITMAP bm;
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps;);
            HDC hdcMem = CreateCompatibleDC(hdc);
            HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmBall);
            GetObject(g_hbmBall, sizeof(bm), &bm;);
            BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
            SelectObject(hdcMem, hbmOld);
            DeleteDC(hdcMem);
            EndPaint(hwnd, &ps;);
            }
        break;
        case WM_COMMAND:
            switch (LOWORD(wParam)) 
            {
                 case IDM_ABOUT:
                 {
                   int ret = (int)DialogBox(GetModuleHandle(NULL), 
                       MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
                   if(ret == -1)
                      MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
                                       MB_OK | MB_ICONINFORMATION);
                }
                break;
                case IDM_EXIT:
                    PostQuitMessage(0);
                break;
            }
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            DeleteObject(g_hbmBall);
            PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));


    if (!RegisterClassEx(&wc;)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while (GetMessage(&Msg;, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg;);
        DispatchMessage(&Msg;);
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}


resource.h
#define IDR_MYMENU           101
#define IDI_MYICON           201
#define IDC_MYICON           202
#define IDM_EXIT            9001
#define IDM_ABOUT           9002
#define IDD_ABOUT           9003
#define IDC_STATIC            -1
#define IDB_BALL             203

win13rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F;)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X;)",             IDM_EXIT
    END
    POPUP "ヘルプ(&H;)"
    BEGIN
        MENUITEM "バージョン情報(&A;)...",              IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"
IDB_BALL BITMAP "ball.bmp"
IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win13 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
ビットマップアニメーションのアプリを作成します。まずは, リソースのビットマップを表示するだけのプログラムです。 WM_CREATE:で作成したg_hbmBallをWM_DESTROY:でDeleteObjectしています。 WM_PAINT:で描画すると必要な自動的に再描画してくれます。

[Transparent Bitmaps]

win14.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam);

HBITMAP g_hbmBall = NULL;
HBITMAP g_hbmMask = NULL;

HBITMAP CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent) {
    HDC hdcMem, hdcMem2;
    HBITMAP hbmMask;
    BITMAP bm;

    GetObject(hbmColour, sizeof(BITMAP), &bm);
    hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);

    hdcMem = CreateCompatibleDC(0);
    hdcMem2 = CreateCompatibleDC(0);

    SelectObject(hdcMem, hbmColour);
    SelectObject(hdcMem2, hbmMask);

    SetBkColor(hdcMem, crTransparent);

    BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);

    BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem2, 0, 0, SRCINVERT);

    DeleteDC(hdcMem);
    DeleteDC(hdcMem2);

    return hbmMask;
}

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam) {
    switch (msg) {
        case WM_CREATE:
        g_hbmBall = LoadBitmap(GetModuleHandle(NULL),
        MAKEINTRESOURCE(IDB_BALL));
        if (g_hbmBall == NULL)
            MessageBox(hwnd, TEXT("Could not load IDB_BALL!"), TEXT("Error"), 
                                                   MB_OK | MB_ICONEXCLAMATION);

        g_hbmMask = CreateBitmapMask(g_hbmBall, RGB(0, 0, 0));
        if (g_hbmMask == NULL)
            MessageBox(hwnd, TEXT("Could not create mask!"), TEXT("Error"), 
                                                   MB_OK | MB_ICONEXCLAMATION);
        break;
        case WM_PAINT: {
            BITMAP bm;
            RECT rcClient;
            PAINTSTRUCT ps;

            HDC hdc = BeginPaint(hwnd, &ps;);

            HDC hdcMem = CreateCompatibleDC(hdc);
            HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmMask);

            GetObject(g_hbmBall, sizeof(bm), &bm;);

            GetClientRect(hwnd, &rcClient;);
            FillRect(hdc, &rcClient;, (HBRUSH)GetStockObject(LTGRAY_BRUSH));

            BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
            BitBlt(hdc, bm.bmWidth, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCAND);
            BitBlt(hdc, bm.bmWidth * 2, bm.bmHeight * 2, bm.bmWidth, 
                                           bm.bmHeight, hdcMem, 0, 0, SRCAND);

            SelectObject(hdcMem, g_hbmBall);
            BitBlt(hdc, 0, bm.bmHeight, bm.bmWidth, bm.bmHeight, hdcMem, 
                                                               0, 0, SRCCOPY);
            BitBlt(hdc, bm.bmWidth, bm.bmHeight, bm.bmWidth, 
                                                   bm.bmHeight, hdcMem,
                                                              0, 0, SRCPAINT);
            BitBlt(hdc, bm.bmWidth * 2, bm.bmHeight * 2, bm.bmWidth,
                                                   bm.bmHeight, hdcMem, 
                                                              0, 0, SRCPAINT);

            SelectObject(hdcMem, hbmOld);
            DeleteDC(hdcMem);

            EndPaint(hwnd, &ps;);
        }
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDM_ABOUT: {
                int ret = (int)DialogBox(GetModuleHandle(NULL),
                               MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
                if (ret == -1)
                    MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
                               MB_OK | MB_ICONINFORMATION);
            }
            break;
            case IDM_EXIT:
            PostQuitMessage(0);
            break;
        }
        break;
        case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
        DeleteObject(g_hbmBall);
        DeleteObject(g_hbmMask);

        PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));


    if (!RegisterClassEx(&wc;)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 160,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while (GetMessage(&Msg;, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg;);
        DispatchMessage(&Msg;);
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}


resource.h
#define IDR_MYMENU         101
#define IDI_MYICON         201
#define IDC_MYICON         202
#define IDM_EXIT          9001
#define IDM_ABOUT         9002
#define IDD_ABOUT         9003
#define IDC_STATIC          -1
#define IDB_BALL           203

win14rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F;)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X;)",         IDM_EXIT
    END
    POPUP "ヘルプ(&H;)"
    BEGIN
        MENUITEM "バージョン情報(&A;)...",              IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"
IDB_BALL BITMAP "ball.bmp"

IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win14 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
CreateBitmapMaskでビットマップのマスクを作成しています。 隅からの5パターンは,ビットマップとマスクの重ね合わせ方の違いによる 表示結果の違いを示しています。マスクをSRCANDで表示した場所にビットマップを SRCPAINTで重ねると背景に左右されずにきれいに表示できます。

[Timers and Animation]

win15.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam);

const int ID_TIMER = 1;
const int BALL_MOVE_DELTA = 5;

typedef struct _BALLINFO {
    int width;
    int height;
    int x;
    int y;

    int dx;
    int dy;
}
BALLINFO;

BALLINFO g_ballInfo;
HBITMAP g_hbmBall = NULL;
HBITMAP g_hbmMask = NULL;

HBITMAP CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent) {
    HDC hdcMem, hdcMem2;
    HBITMAP hbmMask;
    BITMAP bm;

    GetObject(hbmColour, sizeof(BITMAP), &bm;);
    hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);

    hdcMem = CreateCompatibleDC(0);
    hdcMem2 = CreateCompatibleDC(0);

    SelectObject(hdcMem, hbmColour);
    SelectObject(hdcMem2, hbmMask);

    SetBkColor(hdcMem, crTransparent);

    BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);

    BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem2, 0, 0, SRCINVERT);

    DeleteDC(hdcMem);
    DeleteDC(hdcMem2);

    return hbmMask;
}

void DrawBall(HDC hdc, RECT* prc) {
    HDC hdcBuffer = CreateCompatibleDC(hdc);
    HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, prc->right, prc->bottom);
    HBITMAP hbmOldBuffer = (HBITMAP)SelectObject(hdcBuffer, hbmBuffer);

    HDC hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, g_hbmMask);

    FillRect(hdcBuffer, prc, (HBRUSH)GetStockObject(WHITE_BRUSH));

    BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, 
                           g_ballInfo.height, hdcMem, 0, 0, SRCAND);

    SelectObject(hdcMem, g_hbmBall);
    BitBlt(hdcBuffer, g_ballInfo.x, g_ballInfo.y, g_ballInfo.width, 
                         g_ballInfo.height, hdcMem, 0, 0, SRCPAINT);

    BitBlt(hdc, 0, 0, prc->right, prc->bottom, hdcBuffer, 0, 0, SRCCOPY);

    SelectObject(hdcMem, hbmOld);
    DeleteDC(hdcMem);

    SelectObject(hdcBuffer, hbmOldBuffer);
    DeleteDC(hdcBuffer);
    DeleteObject(hbmBuffer);
}

void UpdateBall(RECT* prc) {
    g_ballInfo.x += g_ballInfo.dx;
    g_ballInfo.y += g_ballInfo.dy;

    if (g_ballInfo.x < 0) {
        g_ballInfo.x = 0;
        g_ballInfo.dx = BALL_MOVE_DELTA;
    } else if (g_ballInfo.x + g_ballInfo.width > prc->right) {
        g_ballInfo.x = prc->right - g_ballInfo.width;
        g_ballInfo.dx = -BALL_MOVE_DELTA;
    }

    if (g_ballInfo.y < 0) {
        g_ballInfo.y = 0;
        g_ballInfo.dy = BALL_MOVE_DELTA;
    } else if (g_ballInfo.y + g_ballInfo.height > prc->bottom) {
        g_ballInfo.y = prc->bottom - g_ballInfo.height;
        g_ballInfo.dy = -BALL_MOVE_DELTA;
    }
}

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam,
LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            UINT ret;
            BITMAP bm;

            g_hbmBall = LoadBitmap(GetModuleHandle(NULL),
            MAKEINTRESOURCE(IDB_BALL));
            if (g_hbmBall == NULL)
                MessageBox(hwnd, TEXT("Could not load IDB_BALL!"), 
                            TEXT("Error"), MB_OK | MB_ICONEXCLAMATION);

            g_hbmMask = CreateBitmapMask(g_hbmBall, RGB(0, 0, 0));
            if (g_hbmMask == NULL)
                MessageBox(hwnd, TEXT("Could not create mask!"), 
                       TEXT("Error"), MB_OK | MB_ICONEXCLAMATION);

            GetObject(g_hbmBall, sizeof(bm), &bm;);

            ZeroMemory(&g_ballInfo;, sizeof(g_ballInfo));
            g_ballInfo.width = bm.bmWidth;
            g_ballInfo.height = bm.bmHeight;

            g_ballInfo.dx = BALL_MOVE_DELTA;
            g_ballInfo.dy = BALL_MOVE_DELTA;

            ret = (int)SetTimer(hwnd, ID_TIMER, 50, NULL);
            if (ret == 0)
                MessageBox(hwnd, TEXT("Could not SetTimer()!"), TEXT("Error"), 
                                                   MB_OK | MB_ICONEXCLAMATION);
        }
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDM_ABOUT: {
                int ret = (int)DialogBox(GetModuleHandle(NULL),
                              MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
                if (ret == -1)
                    MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
                               MB_OK | MB_ICONINFORMATION);
            }
            break;
            case IDM_EXIT:
            PostQuitMessage(0);
            break;
        }
        break;
        case WM_PAINT: {
            RECT rcClient;
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps;);

            GetClientRect(hwnd, &rcClient;);
            DrawBall(hdc, &rcClient;);

            EndPaint(hwnd, &ps;);
        }
        break;
        case WM_TIMER: {
            RECT rcClient;
            HDC hdc = GetDC(hwnd);

            GetClientRect(hwnd, &rcClient;);

            UpdateBall(&rcClient;);
            DrawBall(hdc, &rcClient;);

            ReleaseDC(hwnd, hdc);
        }
        break;
        case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
        KillTimer(hwnd, ID_TIMER);

        DeleteObject(g_hbmBall);
        DeleteObject(g_hbmMask);

        PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm = LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));


    if (!RegisterClassEx(&wc;)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while (GetMessage(&Msg;, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg;);
        DispatchMessage(&Msg;);
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam,
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}

resource.h
#define IDR_MYMENU           101
#define IDI_MYICON           201
#define IDC_MYICON           202
#define IDM_EXIT            9001
#define IDM_ABOUT           9002
#define IDD_ABOUT           9003
#define IDC_STATIC            -1
#define IDB_BALL             203

win15rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F;)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X;)",         IDM_EXIT
    END
    POPUP "ヘルプ(&H;)"
    BEGIN
        MENUITEM "バージョン情報(&A;)...",              IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"
IDB_BALL BITMAP "ball.bmp"
IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win15 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END


[解説]
WM_TIMER:でビットマップの表示位置を変えてを書き直すことによって ビットマップがウィンドウ内を移動します。これでビットマップアニメーションの プログラム完成です。

[Text and Fonts]

win16.cpp

#include <windows.h>
#include "resource.h"

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam);

HFONT g_hfFont = NULL;
BOOL g_bOpaque = TRUE;

COLORREF g_rgbText = RGB(0, 0, 0);
COLORREF g_rgbBackground = RGB(255, 255, 255);

COLORREF g_rgbCustom[16] = {0};

void DoSelectFont(HWND hwnd) {
    CHOOSEFONT cf = {sizeof(CHOOSEFONT)};
    LOGFONT lf;

    GetObject(g_hfFont, sizeof(LOGFONT), &lf;);

    cf.Flags = CF_EFFECTS | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
    cf.hwndOwner = hwnd;
    cf.lpLogFont = &lf;
    cf.rgbColors = g_rgbText;

    if (ChooseFont(&cf;)) {
        HFONT hf = CreateFontIndirect(&lf;);
        if (hf) {
            g_hfFont = hf;
        } else {
            MessageBox(hwnd, TEXT("Font creation failed!"), TEXT("Error"), 
                                                     MB_OK | MB_ICONEXCLAMATION);
        }

        g_rgbText = cf.rgbColors;
    }
}

void DoSelectColour(HWND hwnd) {
    CHOOSECOLOR cc = {sizeof(CHOOSECOLOR)};

    cc.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ANYCOLOR;
    cc.hwndOwner = hwnd;
    cc.rgbResult = g_rgbBackground;
    cc.lpCustColors = g_rgbCustom;

    if (ChooseColor(&cc;)) {
        g_rgbBackground = cc.rgbResult;
    }
}

void DrawClientSize(HDC hdc, RECT* prc, HFONT hf) {
    TCHAR szSize[100];
    TCHAR szTitle[] = TEXT("These are the dimensions of your client area:");
    HFONT hfOld = (HFONT)SelectObject(hdc, hf);

    SetBkColor(hdc, g_rgbBackground);
    SetTextColor(hdc, g_rgbText);

    if (g_bOpaque) {
        SetBkMode(hdc, OPAQUE);
    } else {
        SetBkMode(hdc, TRANSPARENT);
    }

    DrawText(hdc, szTitle, -1, prc, DT_WORDBREAK);

    wsprintf(szSize, TEXT("{%d, %d, %d, %d}"), prc->left, prc->top, prc->right,
    prc->bottom);
    DrawText(hdc, szSize, -1, prc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

    SelectObject(hdc, hfOld);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, 
LPARAM lParam) {
    switch (msg) {
        case WM_CREATE:
        g_hfFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
        break;
        case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDM_ABOUT: {
                int ret = (int)DialogBox(GetModuleHandle(NULL),
                               MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutDlgProc);
                if (ret == -1)
                    MessageBox(hwnd, TEXT("Dialog failed!"), TEXT("Error"),
                               MB_OK | MB_ICONINFORMATION);
            }
            break;
            case IDM_EXIT:
            PostMessage(hwnd, WM_CLOSE, 0, 0);
            break;
            case ID_FORMAT_FONT:
            DoSelectFont(hwnd);

            InvalidateRect(hwnd, NULL, TRUE);
            UpdateWindow(hwnd);
            break;
            case ID_FORMAT_DEFAULTGUIFONT:
            DeleteObject(g_hfFont);
            g_hfFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);

            InvalidateRect(hwnd, NULL, TRUE);
            UpdateWindow(hwnd);
            break;
            case ID_FORMAT_TEST: {
                HFONT hf;
                HDC hdc;
                long lfHeight;

                hdc = GetDC(NULL);
                lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72);
                ReleaseDC(NULL, hdc);

                hf = CreateFont(lfHeight, 0, 0, 0, 0, TRUE, 0, 0, 0, 0, 0, 0, 0, 
                                                          TEXT("Times New Roman"));

                if (hf) {
                    DeleteObject(g_hfFont);
                    g_hfFont = hf;
                } else {
                    MessageBox(hwnd, TEXT("Font creation failed!"), TEXT("Error"),
                                                        MB_OK | MB_ICONEXCLAMATION);
                }
                InvalidateRect(hwnd, NULL, TRUE);
                UpdateWindow(hwnd);
            }
            break;
            case ID_FORMAT_BACKGROUNDCOLOUR:
            DoSelectColour(hwnd);

            InvalidateRect(hwnd, NULL, TRUE);
            UpdateWindow(hwnd);
            break;
            case ID_FORMAT_OPAQUE:
            g_bOpaque = !g_bOpaque;

            InvalidateRect(hwnd, NULL, TRUE);
            UpdateWindow(hwnd);
            break;
        }
        break;
        case WM_INITMENUPOPUP:
        CheckMenuItem((HMENU)wParam, ID_FORMAT_OPAQUE, MF_BYCOMMAND 
                                | ( g_bOpaque ? MF_CHECKED : MF_UNCHECKED));
        break;
        case WM_PAINT: {
            RECT rcClient;
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps;);

            GetClientRect(hwnd, &rcClient;);

            DrawClientSize(hdc, &rcClient;, g_hfFont);

            EndPaint(hwnd, &ps;);
        }
        break;
        case WM_DESTROY:
        DeleteObject(g_hfFont);

        PostQuitMessage(0);
        break;
        default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize	= sizeof(WNDCLASSEX);
    wc.style	= CS_VREDRAW | CS_HREDRAW;
    wc.lpfnWndProc	= WndProc;
    wc.cbClsExtra	= 0;
    wc.cbWndExtra	= 0;
    wc.hInstance	= hInstance;
    wc.hIcon	= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
    wc.hCursor	= LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = TEXT("myWindowClass");
    wc.hIconSm	= LoadIcon(wc.hInstance, MAKEINTRESOURCE(IDI_MYICON));
    if (!RegisterClassEx(&wc;)) {
        MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(
               WS_EX_CLIENTEDGE,
               TEXT("myWindowClass"),
               TEXT("The title of my window"),
               WS_OVERLAPPEDWINDOW,
               CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
               NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"),
                   MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg;, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg;);
        DispatchMessage(&Msg;);
    }
    return (int)Msg.wParam;
}

BOOL CALLBACK AboutDlgProc(HWND hwnd, UINT Message, WPARAM wParam, 
LPARAM lParam) {
    switch (Message) {
        case WM_COMMAND:
        switch (LOWORD(wParam)) {
            case IDOK:
            EndDialog(hwnd, IDOK);
            break;
        }
        break;
        default:
        return FALSE;
    }
    return TRUE;
}

resource.h
#define IDR_MYMENU                             101
#define IDI_MYICON                             201
#define IDC_MYICON                             202
#define IDM_EXIT                              9001
#define IDM_ABOUT                             9002
#define IDD_ABOUT                             9003
#define IDC_STATIC                              -1
#define ID_FORMAT_FONT                       40002
#define ID_FORMAT_BACKGROUNDCOLOUR           40003
#define ID_FORMAT_OPAQUE                     40004
#define ID_FORMAT_DEFAULTGUIFONT             40005
#define ID_FORMAT_TEST                       40006

win16rc.rc
#include <windows.h>
#include "resource.h"

IDR_MYMENU MENU
BEGIN
    POPUP "ファイル(&F;)"
    BEGIN
        MENUITEM "アプリケーションの終了(&X;)",       IDM_EXIT
    END
    POPUP "フォーマット(&M;)"
    BEGIN
        MENUITEM "フォント(&F;)...",        ID_FORMAT_FONT
        MENUITEM "Default GUI Font",   ID_FORMAT_DEFAULTGUIFONT
        MENUITEM "Times New Roman (12pt, Italics)",  ID_FORMAT_TEST
        MENUITEM SEPARATOR
        MENUITEM "文字背景色(&B;)..",   ID_FORMAT_BACKGROUNDCOLOUR
        MENUITEM "不透明化(&O;)",       ID_FORMAT_OPAQUE
    END
    POPUP "ヘルプ(&H;)"
    BEGIN
        MENUITEM "バージョン情報(&A;)...",            IDM_ABOUT
    END
END

IDI_MYICON ICON "my_icon.ico"

IDD_ABOUT DIALOGEX 0, 0, 180, 50
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "バージョン情報"
FONT 9, "MS UI Gothic", 0, 0, 0x0
BEGIN
    ICON            IDI_MYICON,IDC_MYICON,14,9,20,20
    LTEXT           "win16 Version 1.0",IDC_STATIC,49,10,119,8,SS_NOPREFIX
    LTEXT           "Copyright (C) 2007",IDC_STATIC,49,20,119,8
    DEFPUSHBUTTON   "OK",IDOK,140,6,30,11,WS_GROUP
END

[解説]
フォント表示のサンプルアプリケーションです。フォントをダイアログから選んだり フォントのサイズや背景色を変更できます。

LESSON2| LESSON4