...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

win32.windows (UNICODE)

完全版はこちら → http://d.hatena.ne.jp/haru-s/20060829/1156868081

いろんな物の中の人ありがとうございます.

やっと動いたー.詳細は続きをどうぞ.

D言語 Part9
http://pc8.2ch.net/test/read.cgi/tech/1146656260/683

683 名前:デフォルトの名無しさん[sage] 投稿日:2006/08/28(月) 21:37:15
win32.windowsが落ちる原因はwinnt.dの
const uint SECURITY_DESCRIPTOR_MIN_LENGTH = SECURITY_DESCRIPTOR.sizeof;
の行っぽい。

const uint SECURITY_DESCRIPTOR_MIN_LENGTH = 20;
とか
const uint SECURITY_DESCRIPTOR_MIN_LENGTH = _SECURITY_DESCRIPTOR.sizeof;
に編集すると落ちない。

んで見つけた。
//クラッシュ再現コード
const int fooSize = Foo.sizeof;
struct tagFoo {}
alias tagFoo Foo;
void main(){}

ありがたやーありがたやー.自力で調べてみたけどわからなかったのでー.
これを修正しただけだと, import がデフォルトで private になった仕様変更に引っかかってまだコンパイルできなかった.面倒なのでまとめて public {} で囲んでやったら win32.windows が使えるようになった.
ただ,UNICODE だったら問題なく動いたんだけど,一通り ANSI に修正してコンパイルしたときに日本語を使うとうまくいかなかった.なんでだろー.

static const TCHAR[] text = "D言語はWindowsも出来る";

この文の何がおかしいのかわからない・・・ orz

#追記 わかったー.UNICODE & ANSI 両方で使えるコードはまた明日.


"windows.h for D" の中の人に感謝しつつ,動いたソースをぺたぺた.
ビルドするときは,ソースファイルを UTF8 で書くことと,Gdi32.lib win32.lib win32.def と一緒にコンパイルすることに注意しませう.

// UNICODE or ANSI
version = UNICODE;
//version = ANSI; // なぜか "D言語はWindowsも出来る" が不正になる?

import std.utf;

version(ANSI)
{
    import win32.ansi.windows;
    char[] toT(char[] t){
        wchar[] s = toUTF16(t);
        char[] result;
        result.length = WideCharToMultiByte(0, 0, s, s.length, null, 0, null, null);
        WideCharToMultiByte(0, 0, s, s.length, result, result.length, null, null);
        return t; 
    }
}
else
{
    import win32.windows;
    alias toUTF16 toT;
}

static const uint IDC_BTNCLICK = 101;
static const uint IDC_BTNDONTCLICK = 102;

// ユーザーコード
int user_main()
{
    HINSTANCE hInst = GetModuleHandle(null);
    WNDCLASS wc;
    wc.lpszClassName = "DFRAME";
    wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = &WindowProc;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(null, IDI_APPLICATION);
    wc.hCursor = LoadCursor(null, IDC_CROSS);
    wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
    wc.lpszMenuName = null;
    wc.cbClsExtra = wc.cbWndExtra = 0;
    ATOM r = RegisterClass(&wc);
    assert(r);
    
    auto frame = createFrame("win32.windows using dmd 0.165", 100, 100, 400, 300, 0, null);
    auto buttonClick = createButton("Click Me", 0, 0, 150, 25, IDC_BTNCLICK, frame);
    auto buttonDontClick = createButton("DONT'T CLICK!", 160, 0, 150, 25, IDC_BTNDONTCLICK, frame);
    
    MSG msg;
    while (GetMessage(&msg, null, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    return -1;
}

HWND createButton(TCHAR[] title, int x, int y, int width, int height, int idc, HWND parent = null)
{
    auto hInst = GetModuleHandle(null);
    auto hWnd = CreateWindow("BUTTON", title, WS_CHILD | WS_VISIBLE,
        x, y, width, height, parent, cast(HMENU)idc, hInst, null);
    return hWnd;
}

HWND createFrame(TCHAR[] title, int x, int y, int width, int height, int idc, HWND parent = null)
{
    auto hInst = GetModuleHandle(null);
    auto hWnd = CreateWindow("DFRAME", title, WS_THICKFRAME |
        WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT, width, height, HWND_DESKTOP,
        cast(HMENU)idc, hInst, null);
    assert(hWnd);
    return hWnd;
}

//  以下、windows用のスタートアップコード
//  \dmd\src\phobos\dmain2.dにある
//  コンソール版のD言語のスタートアップコードと比較してみてください。
//  
//  .defファイルとして、最低限以下のことを書いたファイルを用意して
//  コンパイル時に、そのdefファイルを指定してください。
//      EXETYPE NT
//      SUBSYSTEM WINDOWS

extern (C)
{
    void gc_init();
    void gc_term();
    void _minit();
    void _moduleCtor();
    void _moduleUnitTests();
}

extern (Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int result;
    
    gc_init();          // initialize garbage collector
    _minit();           // initialize module constructor table
    
    try
    {
        _moduleCtor();      // call module constructors
        _moduleUnitTests(); // run unit tests (optional)
    
        result = user_main();  // ユーザーコードはここに入れる
    }
    
    catch (Object o)        // catch any uncaught exceptions
    {
        MessageBox(null, toT(o.toString() ~ "\0"), "Error", MB_OK | MB_ICONEXCLAMATION);
        result = 0;     // failed
    }
    
    gc_term();          // run finalizers; terminate garbage collector
    return result;
}

extern(Windows)
uint WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_COMMAND:
        {
            switch (LOWORD(wParam))
            {
                case IDC_BTNCLICK:
                    if (HIWORD(wParam) == BN_CLICKED)
                    {
                        MessageBox(hWnd, "Hello, world!", "こんにちは", MB_OK | MB_ICONINFORMATION);
                    }
                    break;
                case IDC_BTNDONTCLICK:
                    if (HIWORD(wParam) == BN_CLICKED)
                    {
                        MessageBox(hWnd,
                            "わざとメモリ保護違反を出します", "メモリ保護違反出すよー",
                            MB_OK | MB_ICONEXCLAMATION);
                        *(cast(int*) null) = 666;
                    }
                    break;
            }
            break;
        }
        
        case WM_PAINT:
        {
            static const TCHAR[] text = "D言語はWindowsも出来る";
            PAINTSTRUCT ps;
            HDC dc = BeginPaint(hWnd, &ps);
            RECT r;
            GetClientRect(hWnd, &r);
            HFONT font = CreateFont(80, 0, 0, 0, FW_EXTRABOLD, FALSE, FALSE,
                FALSE, /*ANSI_CHARSET*/ SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS,
                CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "MS明朝");
            HGDIOBJ old = SelectObject(dc, font);
            SetTextAlign(dc, TA_CENTER | TA_BASELINE);
            TextOut(dc, r.right / 2, r.bottom / 2, text, text.length);
            SelectObject(dc, old);
            EndPaint(hWnd, &ps);
            break;
        }
        
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        
        default:
            break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}