Windowsプログラミングメモ2

by K.I

Index


概要


[top]

描画関連

PaintControlに描画する。

        RECT rt;
        HWND hctrl;
        HDC hdc;

        hctrl = GetDlgItem(hdlg1,IDC_GRAPH);
        GetWindowRect(hctrl,&rt);
        hdc = GetDC(hctrl);
        StretchBlt(hdc,0,0,rt.right-rt.left,rt.bottom-rt.top,
        hbuffer,0,0,bufx,bufy,SRCCOPY);
        ReleaseDC(hctrl,hdc);

図形表示の基本

キレイなカラーテーブルを作る

// HSV色空間→RGBへ変換(HSVは0〜1に正規化)
COLORREF hsv2rgb(double h, double s, double v)
{
        double i,f,p,q,t;

        if ( s == 0 ){                  // グレイスケール
                return(RGB(v*255,v*255,v*255));
        }
        else {                          // S=0以外
                if (1.0 <= h)
                        h -= 1.0;

                h *= 6.0;
                i = floor (h);
                f = h - i;
                p = v * (1 - s);
                q = v * (1 - (s * f));
                t = v * (1 - (s * (1 - f)));

                if( i < 1 )
                        return(RGB(v*255,t*255,p*255));
                else if( i < 2 )
                        return(RGB(q*255,v*255,p*255));
                else if( i < 3 )
                        return(RGB(p*255,v*255,t*255));
                else if( i < 4 )
                        return(RGB(p*255,q*255,v*255));
                else if( i < 5 )
                        return(RGB(t*255,p*255,v*255));
                else
                        return(RGB(v*255,p*255,q*255));
        }
}

[top]

サブクラス化

ピクチャコントロールのサブクラス化

LRESULT CALLBACK piccon_subproc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
        PAINTSTRUCT ps;
        HDC hdc;
        RECT rt;

        switch (msg) {
        // 再描画処理を追加してみた
        case WM_PAINT:
                GetWindowRect(hWnd,&rt);
                hdc = BeginPaint(hWnd, &ps);
                StretchBlt(hdc,0,0,rt.right-rt.left,rt.bottom-rt.top,
                        cg.hbuffer,0,0,cg.bufx,cg.bufy,SRCCOPY);
                EndPaint(hWnd, &ps);
                break;
        }

        // 続けて、本来のピクチャコントロールの処理をおこなう
        return CallWindowProc((WNDPROC)ppiccon,hWnd,msg,wp,lp);
}

URLリンク

URLリンク2


1WM_PAINTをメインのWindow以外で行うのは、どうもマズイようだ。

[top]

ウィンドウ関連

ウィンドウ位置の保存

void SaveWindowState(HWND hWnd, char *symnam)
{
        str255 line;
        WINDOWPLACEMENT w;

        // ウィンドウ位置・状態取得
        w.length = sizeof(WINDOWPLACEMENT);
        GetWindowPlacement(hWnd, &w);

        // ウィンドウ位置、状態保存(1〜4項目に位置、5項目にZoom状態)
        if (w.showCmd == SW_SHOWMAXIMIZED) {
                sprintf(line,"%d,%d,%d,%d,1",
                        w.rcNormalPosition.left,w.rcNormalPosition.bottom,
                        w.rcNormalPosition.right,w.rcNormalPosition.top);
        }
        else {
                sprintf(line,"%d,%d,%d,%d,0",
                        w.rcNormalPosition.left,w.rcNormalPosition.bottom,
                        w.rcNormalPosition.right,w.rcNormalPosition.top);
        }
        set_symbol(symnam,line);                // symnamで保存
}

ウィンドウ位置の復元

void LoadWindowState(HWND hWnd, char *symnam)
{
        WINDOWPLACEMENT w;
        RECT rcWnd;
        MONITORINFO mi;
        str255 line;

        // 既定のウィンドウ位置取得
        w.length = sizeof(WINDOWPLACEMENT);
        GetWindowPlacement(hWnd, &w);
        get_rectsym(&rcWnd,symnam,&w.rcNormalPosition); // 1〜4項目の前回のWin位置を取得

        // 対象モニタの情報を取得
        HMONITOR hMonitor = MonitorFromRect(&rcWnd, MONITOR_DEFAULTTONEAREST);
        mi.cbSize = sizeof(MONITORINFO);
        GetMonitorInfo(hMonitor, &mi);

        // 位置補正
        if (rcWnd.right > mi.rcMonitor.right) {
                rcWnd.left -= rcWnd.right - mi.rcMonitor.right;
                rcWnd.right = mi.rcMonitor.right;
        }
        if (rcWnd.left < mi.rcMonitor.left) {
                rcWnd.right += mi.rcMonitor.left - rcWnd.left;
                rcWnd.left = mi.rcMonitor.left;
        }
        if (rcWnd.bottom > mi.rcMonitor.bottom) {
                rcWnd.top -= rcWnd.bottom - mi.rcMonitor.bottom;
                rcWnd.bottom = mi.rcMonitor.bottom;
        }
        if (rcWnd.top < mi.rcMonitor.top) {
                rcWnd.bottom += mi.rcMonitor.top - rcWnd.top;
                rcWnd.top = mi.rcMonitor.top;
        }

        // ウィンドウ位置復元
        SetWindowPos(hWnd, NULL, rcWnd.left, rcWnd.top,
        rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, SWP_NOZORDER);

        // ウィンドウ最大化状態復元                     // 5項目の前回のZoom状態取得
        get_dsym(line,symnam,",,,,0",255);              // symnamから読出し
        if (iitem(line,5)) ShowWindow(hWnd, SW_MAXIMIZE);
}

ウィンドウサイズの制限


[top]

リストビュー

項目名を追加

void InsColumn(HWND hWnd, char *str, int cx, int iSub)
{
        LV_COLUMN col;

        col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
        col.fmt = LVCFMT_LEFT;
        col.cx = cx;
        col.pszText = str;
        col.iSubItem = iSub;
        ListView_InsertColumn(hWnd, iSub, &col);
        return;
}

行の追加

void InsItem(HWND hWnd, int item, char *str)
{
        LV_ITEM itm;

        itm.mask = LVIF_TEXT;
        itm.pszText = str;
        itm.iItem = item;
        itm.iSubItem = 0;
        ListView_InsertItem(hWnd, &itm);
        return;
}

データのセット

void SetSubitem(HWND hWnd, int item, int subitem, char *str)
{
        LV_ITEM itm;

        itm.mask = LVIF_TEXT;
        itm.pszText = str;
        itm.iItem = item;
        itm.iSubItem = subitem;

        ListView_SetItem(hWnd, &itm);
        return;
}

リストビューの削除

void listview_delallcol(HWND hlistview)
{
        int i,count;

        //カラム数を求める
        count = Header_GetItemCount(ListView_GetHeader(hlistview));

        for (i=0; i<count ;i++) {
                ListView_DeleteColumn(hlistview,0);
        }
}

カスタムドロー

カスタムドローは最初はうまく行かなかった。自分が引っ掛かったのは以下のようなこと。

仮想リストビュー

手順としては、
case WM_NOTIFY:
        LPNMHDR lpnmhdr;
        lpnmhdr = (LPNMHDR)lp;

        if (lpnmhdr->hwndFrom == g.hbtable) {   // BINTABLEからのメッセージであることをチェック
                switch ( lpnmhdr->code ) {
                case LVN_GETDISPINFO :

                        LV_DISPINFO *pLvDispInfo;
                        pLvDispInfo = (LV_DISPINFO*)lp;
                        TCHAR szString[MAX_PATH];
        
                        if (pLvDispInfo->item.mask & LVIF_TEXT) {       // TEXTならば
                                col = pLvDispInfo->item.iSubItem;       // 列番号
                                row = pLvDispInfo->item.iItem;          // 行番号

                                wsprintf(szString,"%d,%d",col,row);     // とりあえず列行を出力
                                if (lstrlen(szString) < pLvDispInfo->item.cchTextMax)
                                        lstrcpy(pLvDispInfo->item.pszText,szString);
                                else
                                        lstrcpy(pLvDispInfo->item.pszText,_T(""));
                        }
                        break;
                default :
                        break;
                }       // end of switch(lpnmhdr->code)
        }       // end of (hwndFrom == g.hbtable) 

        return TRUE;

オーナードロー

Click位置のチェック

行の選択

選択行のチェック

選択色の変更(未解決)

ListViewの再表示

ListViewの使い方の例


2CDDS_ITEMPREPAINTイベントが来ない場合はコレを疑うこと。
3フォーカスが何処だか分からなくなってしまった。
4ListViewの列方向は取って付けたような中途半端な仕様。初めから2次元を扱うように作ってあれば、すっきりしたのに。

[top]

キー入力

キー入力イベント

        case WM_KEYDOWN:
                switch (wp) {
                        case VK_RIGHT:
                                // →キーの処理;
                                break;
                        case VK_LEFT:
                                // ←キーの処理;
                                break;
                }
                return TRUE;

複数キー入力

Dialogのキー入力


[top]

DLL関連

DLLの遅延ロード

DLLからLIBを作る

ActiveX DLL


[top]

その他

FileOpenDialog

#include <commdlg.h>
        :
BOOL openfile_dialog(HWND hWnd, TCHAR *defa_file, TCHAR *title, TCHAR *filter)
{
        OPENFILENAME OpenFileName;

        OpenFileName.lStructSize       = sizeof(OPENFILENAME);
        OpenFileName.hwndOwner         = hWnd;
        OpenFileName.hInstance         = NULL;
        OpenFileName.lpstrFilter       = filter;

        OpenFileName.lpstrCustomFilter = NULL;
        OpenFileName.nMaxCustFilter    = 0;
        OpenFileName.nFilterIndex      = 0;
        OpenFileName.lpstrFile         = defa_file;
        OpenFileName.nMaxFile          = 511;
        OpenFileName.lpstrFileTitle    = NULL;
        OpenFileName.nMaxFileTitle     = 0;
        OpenFileName.lpstrInitialDir   = NULL;
        OpenFileName.lpstrTitle        = title;
        OpenFileName.nFileOffset       = 0;
        OpenFileName.nFileExtension    = 0;
        OpenFileName.lpstrDefExt       = NULL;
        OpenFileName.lCustData         = NULL;
        OpenFileName.Flags             = OFN_EXPLORER |  OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT;

        return GetOpenFileName(&OpenFileName);
}

FileSaveDialog

Fileダイアログのカスタマイズ

フォルダ選択ダイアログ

フォルダをListBoxに表示

ファイル一覧の取得

他のプログラムを実行

スピンコントロール


[top]

参考

このメモを記述するにあたって、参考にさせて頂いたサイト。或いは参考になりそうなサイト。

comments powered by Disqus