/* ubuntu14.04.c coded by isaku@pb4.so-net.ne.jp
Ubuntu14.04+Wineでウィンドウの位置が下にずれるのを防ぐ

Ubuntu14.04 ではウィンドウの位置を記録するようなプログラムは、ほとんどの
場合、プログラムを起動するごとに28ピクセルずつ下にずれる。
Wine 上で動くプログラムも例外ではない。Ubuntu12.04 ではこの現象は起きない。

ここでは、Wine で開発する場合に下にずれないようにする方法を説明する。

ずれる現象を自分で調べた所、以下のことが分かった。
・CreateWindow に渡した位置情報は CreateWindow 後でも変化しない。
・ShowWindow(hwnd,SW_SHOW) を行った直後でも位置は変化しない。
・しかし、表示が終わると28ピクセル下にずれる。
・この時、WM_MOVE は送られない。
・しかし、メッセージループに入ると WM_MOVE が送られる。
・逆に ShowWindow(hwnd,SW_HIDE) を行った場合は上に28ピクセルずれる。

そして、この問題を調べているときに以下の知識も得た。
・Wine の UpdateWindow(hwnd) は Windows とは違い、ウィンドウプロシージャを
 呼び出すのではなく、WM_PAINT を hwnd に送る。従ってメッセージループに
 進むまで描画はされない。
・Wine でも Windows でも、MoveWindow(hwnd,x,y,w,h,TRUE) の描画は
 ウィンドウプロシージャを呼び出すのではなく、WM_PAINT を hwnd に送る。
 従って、これもメッセージループに進むまで描画はされない。

以下に、この現象を防ぐ方法の例を示す。
これは、ウィンドウに楕円形を描画するプログラムである。
実行ファイルの拡張子を .exe から .cfg に置き換えたファイルに位置を記録する。

*/

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

#define USE_MOVE_WINDOW 1  /* これを1にするとUbuntu14.04のバグを回避      */
RECT Pos={200,200,200,200};/* ウィンドウの位置と大きさを記録する変数       */
char Cfg[MAX_PATH];        /* ウィンドウの位置と大きさを記録するファイル名 */

LRESULT CALLBACK WndProc(HWND hwnd,UINT wm,WPARAM wp,LPARAM lp) {
    RECT r; FILE*fp; HDC dc; PAINTSTRUCT ps;
    switch (wm) {
    case WM_PAINT: dc=BeginPaint(hwnd,&ps); GetClientRect(hwnd,&r);
        Ellipse(dc,r.left,r.top,r.right,r.bottom);
        EndPaint(hwnd,&ps); return 0;
    case WM_SIZE: case WM_MOVE:
        GetWindowRect(hwnd,&Pos); Pos.right-=Pos.left; Pos.bottom-=Pos.top;
        InvalidateRect(hwnd,0,TRUE); return 0;
    case WM_CLOSE: fp=fopen(Cfg,"wb"); fwrite(&Pos,1,sizeof Pos,fp);
        fclose(fp); DestroyWindow(hwnd); return 0;
    case WM_DESTROY: PostQuitMessage(0); return 0;
    default: return DefWindowProc(hwnd,wm,wp,lp);
    }
}

int WINAPI WinMain(HINSTANCE hinst,HINSTANCE prv,LPSTR arg,int cmd) {
    WNDCLASSEXA w={sizeof w,0,WndProc,0,0,0,0,0,(HBRUSH)(size_t)6,0,"TEST"};
    HWND hwnd; MSG msg; FILE*fp; static void*du; du=&prv; du=&arg; du=&cmd;
    w.hInstance=hinst;    w.hCursor=LoadCursorA(0,IDC_ARROW);
    RegisterClassExA(&w); GetModuleFileNameA(0,Cfg,MAX_PATH);
    lstrcpyA(Cfg+lstrlenA(Cfg)-4,".cfg"); fp=fopen(Cfg,"rb");
    if (fp) { fread(&Pos,1,sizeof Pos,fp); fclose(fp); }
    hwnd=CreateWindow("TEST","TEST",WS_OVERLAPPEDWINDOW,
        Pos.left,Pos.top,Pos.right,Pos.bottom,HWND_DESKTOP,0,hinst,0);
    ShowWindow(hwnd,SW_SHOW);
#if USE_MOVE_WINDOW
    Sleep(10); MoveWindow(hwnd,Pos.left,Pos.top,Pos.right,Pos.bottom,FALSE);
#endif
    UpdateWindow(hwnd);
    while (GetMessageA(&msg,0,0,0))
    { TranslateMessage(&msg); DispatchMessageA(&msg); }
    return msg.wParam;
}