発行するクエリを編集する


DialogBox で編集したクエリを発行して List Control に表示します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. ページ先頭の画像を参考にして、DialogBox を作成して下さい。
    メニューに「SQL の発行(IDM_QUERY)」を追加して下さい。
  2. sql_file[] は TEXT 形式の SQL のテンプレートファイルです。
    sql.txt のソースをこの後に掲載します。
    szSQL[] は実行する SQL の領域で、初期値として全レコードを抽出する SQL を格納しています。
    sqlt[][] は SQL の説明とソースを格納するテーブルで、g_cnt はその件数です。
        /********************************************************/
        /*★ クエリを発行して List View に表示する    前田 稔 ★*/
        /********************************************************/
        #define     NAME    "Query"
        #include    <windows.h>
        #include    <commctrl.h>
        #include    <mysql.h>
        #include    "resource.h"
        #pragma     comment(lib,"comctl32.lib")
        #pragma     comment(lib,"libmysql.lib")
        #define     ID_LISTVIEW     (WM_APP + 0)
    
        // 使用するデータベース
        #define     szDB    "mark"
        // 発行するクエリ(Dialog Box で設定する)
        char        szSQL[120]= "SELECT * FROM mark_table";
    
        // MYSQLの定義
        MYSQL       *myData= NULL;      // MySQL の Object
        MYSQL_RES   *res= NULL;         // クエリの Object
        UINT        Count;              // Record 件数
        MYSQL_ROW   row;                // ITEM の領域
    
        HINSTANCE   g_hInst;
        HWND        g_hWnd;
        HWND        g_hList;
    
        char    HEAD[][6]=  {  "番号", "名前", "数学", "英語", "理科"  };
        int     CX[]=       {  80, 100, 60, 60, 60  };
        char    sql_file[]= "sql.txt";  // SQL のテンプレートファイル
        char    sqlt[100][120];         // 説明 & SEQ
        int     g_cnt;                  // sqlt[][] の登録件数
        char    buf[3004];              // sql.txt の入力バッファ
        
  3. sql.txt のソースコードです。
    SQL の説明とそのソースが対になって記録されています。
    用途に合わせて、エディッタで自由に追加/修正することが出来ます。
    全てのレコードを抽出する
    SELECT * FROM mark_table
    数学が50点以上のレコードを抽出する
    SELECT * FROM mark_table WHERE v1>49
    三科目のどれかが50点以下のレコードを抽出する
    SELECT * FROM mark_table WHERE v1<50 OR v2<50 OR v3<50
    三科目が全て50点以上のレコードを抽出する
    SELECT * FROM mark_table WHERE v1>49 AND v2>49 AND v3>49
    三科目の合計が150点以下のレコードを抽出する
    SELECT * FROM mark_table WHERE v1+v2+v3<150
    番号が100のレコードを抽出する
    SELECT * FROM mark_table WHERE no=100
    名前に「子」が付くレコードを抽出する
    SELECT * FROM mark_table WHERE name LIKE '%子%'
    名前が「山」で始まるレコードを抽出する
    SELECT * FROM mark_table WHERE name LIKE '山%'
  4. sql_file[] を入力して sqlt[100][120] に格納する関数です。
    説明とソースが交互に繰り返して格納されます。
        //★ テンプレートをテーブルに格納
        int  SetMsg(char *file)
        {   HANDLE  hFile;
            DWORD   dwBytes,p,q;
            int     cnt;
    
            hFile = CreateFile(file,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
            if (hFile==INVALID_HANDLE_VALUE)
            {   MessageBox(NULL,"SQL File Open Error",file, MB_OK);
                return 0;
            }
            ReadFile(hFile,buf,3000,&dwBytes,NULL);
            buf[dwBytes]= '\0';
            CloseHandle(hFile);
            // sqlt[100][120] に格納
            for(cnt=p=0; p<dwBytes; cnt++)
            {   for(q=p; buf[q]!='\r'; q++);
                buf[q]= '\0';
                strcpy(sqlt[cnt],&buf[p]);
                if (q+12>dwBytes)   break;  //最後のゴミ
                p= q+2;
            }
            return cnt/2;
        }
        
  5. WinMain() の最初で SetMsg() 関数をコールして、sql_file を sqlt[][] に格納します。
    SelectSQL() 関数は、クエリ(szSQL)を発行する関数です。
        //★ Windows Main 関数
        int APIENTRY  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
        {   MSG         msg;
    
            g_hInst= hInst;
            if ((g_cnt=SetMsg(sql_file))==0)    return FALSE;
            if (SelectSQL(szSQL)==FALSE)        return FALSE;
                :
            // プログラムの終了
            if (res)    mysql_free_result(res);
            if (myData) mysql_close(myData);
    
            return S_OK;
        }
        
  6. WM_CREATE: では List View のウインドウを生成してメインウインドウに貼り付けます。
    SetListView() で最初に抽出されたレコードを List View に登録します。
        //★ ウィンドウプロシージャ
        LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
        {
            switch (msg)
            {   case WM_CREATE:
                    InitCommonControls();
                    g_hList = CreateWindowEx(0,
                        WC_LISTVIEW, "",
                        WS_CHILD | WS_VISIBLE | LVS_REPORT,
                        0, 0, 0, 0,
                        hWnd, (HMENU)ID_LISTVIEW, g_hInst, NULL);
                    SetListView(g_hList);
                    break;
                case WM_SIZE:
                    MoveWindow(g_hList,0,0,LOWORD(lp),HIWORD(lp),TRUE);
                    break;
        
  7. メニューからクエリの発行(IDM_QUERY:)が選択されると DialogBox を表示します。
    リターン値が TRUE のときは、クエリを発行して新しく抽出したレコードを ListView に表示します。
                case WM_COMMAND:
                    switch(LOWORD(wp))
                    {   case IDM_QUERY:
                            if (DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)DlgProc)==TRUE)
                            {   if (SelectSQL(szSQL)==TRUE) SetListView(g_hList);
                            }
                            break;
                                :
        
  8. DialogBox の CALLBACK 関数です。
    WM_INITDIALOG: で CombBox に sqlt[] の SQL の説明を登録します。
    SQL選択(IDC_SEL:)ボタンがクリックされると、CombBox に対応する SQL を EditBox に表示します。
    EditBox の SQL を用途に応じて編集することが出来ます。
    SQL の編集が終わるとOK(IDOK)ボタンをクリックします。
    EditBox の SQL を szSQL に格納してクエリを発行します。
        //★ Dialog Box の CALLBACK 関数
        LRESULT CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
        {   int     i,item;
    
            switch (msg)
            {   case WM_INITDIALOG:
                    for(i=0; i<g_cnt; i++)
                        SendMessage(GetDlgItem(hDlg,IDC_COMBO1),CB_INSERTSTRING,(WPARAM)i,(LPARAM)sqlt[i*2]);
                    SendMessage(GetDlgItem(hDlg,IDC_COMBO1),CB_SETCURSEL,(WPARAM)0L,0L);
                    break;
                case WM_COMMAND:
                    switch (LOWORD(wp))
                    {   case IDC_SEL:   //CombBox の SQL を EditBox に格納
                            item = (int)(DWORD)SendMessage(GetDlgItem(hDlg,IDC_COMBO1),CB_GETCURSEL,0L,0L);
                            SetDlgItemText(hDlg,IDC_EDIT1,sqlt[item*2+1]);
                            break;
                        case IDOK:      //EditBox の SQL を szSQL に格納する
                            GetDlgItemText(hDlg,IDC_EDIT1,szSQL,120);
                            EndDialog(hDlg,TRUE);
                            return TRUE;
                        case IDCANCEL:
                            EndDialog(hDlg,FALSE);
                            return TRUE;
                    }
                    break;
                case WM_CLOSE:
                    EndDialog(hDlg,TRUE);
                    return TRUE;
            }
            return FALSE;
        }
        
  9. クエリを発行してレコードを抽出する関数は今までと同じです。
    ただ複数回呼ばれることがあるので、前回にオープンされているときは閉じて下さい。
        //★ クエリを発行してレコードを抽出
        HRESULT  SelectSQL(char *sql)
        {   // Close MySQL
            if (res)    mysql_free_result(res);
            if (myData) mysql_close(myData);
                :
        
  10. List View に成績データを登録する関数 SetListView() は以前と同じです。

【演習】

  1. プログラムを完成させて下さい。
  2. メニューからクエリの発行を選んで試してみて下さい。

超初心者のプログラム入門(Win32API C++)