This is “ウインドウズプログラミング講座、第1回、 LCC版“

Since: 3/5/2006 11:31:01 AM

 

              Contact with tkondo001@hotmail.com

 

 

 

ウインドウズプログラミング講座、第1回   LCC

 

 今回のモジュール

Viewers.h      リソースヘッダーファイルである。

View.c          C言語ソースコードである。

 

 

 今回のソースは、最小限の構成となっている。

 つまり、C言語ソースコード1つと、リソース用ヘッダーファイル並びにリソースファイルが1つという、構成である。これは、例えば、BCC版であっても、VCC版であっても変わらず、最小編成である。

 ウインドウズプログラムでなければ、あるいは、リソースを用いない場合には、リソースファイルとリソースヘッダーファイルが無い、C言語ソースコードのみ(1つだけ)ということになる。

 

 

今回の簡単な説明

 

○初めに、WinMain 関数ありきである。

ついで、WinMain 関数のコールバック関数である、MainWndProc 関数がそれに次ぐ。

 

 残りの関数は、ウインドウズプログラムという観点からは、この二つの関数の補足となっている。

 

○ 同様の構成を持っているのが、ダイアログ関連のDialogBox関数(ウインドウズAPI関数である)、とそのコールバック関数である、AboutDlg関数である。

 

 今回の例では、ウインドウ関連の精製とコールバック関数はこの2つのみである。

 

○ちなみに、AboutDlg 関数は、WinMainコールバック関数のMainWndProc関数から、MsgMenuSelect関数、ついで、MainWndProc_OnCommand関数を経て、呼ばれている。

 これは、ちょうど、メニュー選択、とその処理、”About”コマンドとその処理の関係である。ウインドウズプログラミングにおける、メニュー処理の典型といえる関係となっていると言えよう。

 

○ WinMain()関連のユーザー定義初期化関数(view.c で定義されている関数群)については、意見の分かれるところであろう。そのまま、好みの問題といってよい、どーでもいい関数わけとも、いえる、という訳だ。

 

○ステータスバーの処理なども、興味深いところである。初期化(生成、クリエート)関数は別にして、描画・内容の設定、表示・アップデートの関係は、描画などの処理そのままであり、ウインドウズプログラムの特徴をよく芦原和紙していると言えよう。

 

 大体、ここまで説明すると、残りはAPIの具体的な仕様、入力と出力、並びに処理内容の問題となるといえるだろう。つまりは、マニュアルの勉強の問題である。

 

という訳で、後は、それぞれの、プログラムの勉強用の本、又は、関数に関する情報元をあたってみてほしい。

 LCC付属の、API関連ヘルプなどは、格好のデータベースではあるが、いかんせん、構造を持たない羅列であることから、大変な苦労を伴いそうであるが、

 

 今回のソースについての基本的な情報

 

              関数一覧

           関数関係一覧

           グローバル変数一覧

           定数一覧                                今回は省く。

 

 

Download   今回のプロジェクトフォルダーのダウンロード

 

使用ツール等

 

 

 以下にソースコードを掲載する。

 

 

Viewers.h

 

---

/* --- The following code comes from c:\lcc\lib\wizard\stddef.tpl. */

// This are the definitions for all symbols used in menus or string.

#define IDACCEL[t.k1]  10000

#define IDM_NEW 200[t.k2] 

#define IDM_OPEN 210

#define IDM_SAVE 220

#define IDM_SAVEAS 230

#define IDM_CLOSE 240

#define IDM_PRINT 250

#define IDM_PAGESETUP 260

#define IDM_EXIT 300

#define IDM_ABOUT 500

#define IDMAINMENU 600

#define IDAPPLICON [t.k3] 710

#define IDAPPLCURSOR 810

#define IDS_FILEMENU[t.k4]  2000

#define IDS_HELPMENU 2010

#define IDS_SYSMENU 2030

#define IDM_STATUSBAR[t.k5]  3000

#define IDD_ABOUT[t.k6]        100

 

---

 

 

View.c

---

 

/*@@ Wedit generated application. Written Sun Mar 05 09:37:27 2006

 @@header: c:\mywork\c\lcc\view\viewres.h

 @@resources: c:\mywork\c\lcc\view\view.rc

 Do not edit outside the indicated areas */

/*<---------------------------------------------------------------------->*/

/*<---------------------------------------------------------------------->*/

#include <windows.h>

#include <windowsx.h>

#include <commctrl.h>

#include <string.h>

[t.k7] #include "viewres.h"[t.k8] 

/*<---------------------------------------------------------------------->*/

HINSTANCE hInst;               // Instance handle[t.k9] 

HWND hwndMain;                 //Main window handle[t.k10] 

 

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);[t.k11] 

/* --- The following code comes from c:\lcc\lib\wizard\statbar.tpl. */

 

// Global Variables for the status bar control.

 

HWND  hWndStatusbar;[t.k12] 

 

/*------------------------------------------------------------------------

 Procedure:     UpdateStatusBar ID:1

 Purpose:       Updates the statusbar control with the appropiate

                text

 Input:         lpszStatusString: Charactar string that will be shown

                partNumber: index of the status bar part number.

                displayFlags: Decoration flags

 Output:        none

 Errors:        none

 

------------------------------------------------------------------------*/

void UpdateStatusBar(LPSTR lpszStatusString, WORD partNumber, WORD displayFlags)

[t.k13] {

    SendMessage(hWndStatusbar,

                SB_SETTEXT,

                partNumber | displayFlags,

                (LPARAM)lpszStatusString);

}

 

 

/*------------------------------------------------------------------------

 Procedure:     MsgMenuSelect ID:1

 Purpose:       Shows in the status bar a descriptive explaation of

                the purpose of each menu item.The message

                WM_MENUSELECT is sent when the user starts browsing

                the menu for each menu item where the mouse passes.

 Input:         Standard windows.

 Output:        The string from the resources string table is shown

 Errors:        If the string is not found nothing will be shown.

------------------------------------------------------------------------*/

LRESULT MsgMenuSelect(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)

[t.k14] {

    static char szBuffer[256];

    UINT   nStringID = 0;

    UINT   fuFlags = GET_WM_MENUSELECT_FLAGS(wparam, lparam) & 0xffff;

    UINT   uCmd    = GET_WM_MENUSELECT_CMD(wparam, lparam);

    HMENU  hMenu   = GET_WM_MENUSELECT_HMENU(wparam, lparam);

 

    szBuffer[0] = 0;                            // First reset the buffer

    if (fuFlags == 0xffff && hMenu == NULL)     // Menu has been closed

        nStringID = 0;

 

    else if (fuFlags & MFT_SEPARATOR)           // Ignore separators

        nStringID = 0;

 

    else if (fuFlags & MF_POPUP)                // Popup menu

    {

        if (fuFlags & MF_SYSMENU)               // System menu

            nStringID = IDS_SYSMENU;

        else

            // Get string ID for popup menu from idPopup array.

            nStringID = 0;

    }  // for MF_POPUP

    else                                        // Must be a command item

        nStringID = uCmd;                       // String ID == Command ID

 

    // Load the string if we have an ID

    if (0 != nStringID)

        LoadString(hInst, nStringID, szBuffer, sizeof(szBuffer));

    // Finally... send the string to the status bar

    UpdateStatusBar(szBuffer, 0, 0);

    return 0;

}

 

 

/*------------------------------------------------------------------------

 Procedure:     InitializeStatusBar ID:1

 Purpose:       Initialize the status bar

 Input:         hwndParent: the parent window

                nrOfParts: The status bar can contain more than one

                part. What is difficult, is to figure out how this

                should be drawn. So, for the time being only one is

                being used...

 Output:        The status bar is created

 Errors:

------------------------------------------------------------------------*/

void InitializeStatusBar(HWND hwndParent,int nrOfParts)

[t.k15] {

    const int cSpaceInBetween = 8;

    int   ptArray[40];   // Array defining the number of parts/sections

    RECT  rect;

    HDC   hDC;

 

   /* * Fill in the ptArray...  */

 

    hDC = GetDC(hwndParent);

    GetClientRect(hwndParent, &rect);

 

    ptArray[nrOfParts-1] = rect.right;

    //---TODO--- Add code to calculate the size of each part of the status

    // bar here.

 

    ReleaseDC(hwndParent, hDC);

    SendMessage(hWndStatusbar,

                SB_SETPARTS,

                nrOfParts,

                (LPARAM)(LPINT)ptArray);

 

    UpdateStatusBar("Ready", 0, 0);

    //---TODO--- Add code to update all fields of the status bar here.

    // As an example, look at the calls commented out below.

 

//    UpdateStatusBar("Cursor Pos:", 1, SBT_POPOUT);

//    UpdateStatusBar("Time:", 3, SBT_POPOUT);

}

 

 

/*------------------------------------------------------------------------

 Procedure:     CreateSBar ID:1

 Purpose:       Calls CreateStatusWindow to create the status bar

 Input:         hwndParent: the parent window

                initial text: the initial contents of the status bar

 Output:

 Errors:

------------------------------------------------------------------------*/

static BOOL CreateSBar(HWND hwndParent,char *initialText,int nrOfParts)

[t.k16] {

    hWndStatusbar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | WS_BORDER|SBARS_SIZEGRIP,

                                       initialText,

                                       hwndParent,

                                       IDM_STATUSBAR);

    if(hWndStatusbar)

    {

        InitializeStatusBar(hwndParent,nrOfParts);

        return TRUE;

    }

 

    return FALSE;

}

 

int GetFileName(char *buffer,int buflen)[t.k17] 

{

              char tmpfilter[40];

              int i = 0;

              OPENFILENAME ofn;

 

              memset(&ofn,0,sizeof(ofn));

              ofn.lStructSize = sizeof(ofn);

              ofn.hInstance = GetModuleHandle(NULL);

              ofn.hwndOwner = GetActiveWindow();

              ofn.lpstrFile = buffer;

              ofn.nMaxFile = buflen;

              ofn.lpstrTitle = "Open";

              ofn.nFilterIndex = 2;

              ofn.lpstrDefExt = "txt";

              strcpy(buffer,"*.txt");

              strcpy(tmpfilter,"All files,*.*,Text Files,*.txt");

              while(tmpfilter[i]) {

                            if (tmpfilter[i] == ',')

                                          tmpfilter[i] = 0;

                            i++;

              }

              tmpfilter[i++] = 0; tmpfilter[i++] = 0;

              ofn.Flags = 539678;

              ofn.lpstrFilter = tmpfilter;

              return GetOpenFileName(&ofn);

 

}

 

/*<---------------------------------------------------------------------->*/

/*@@0->@@*/

static BOOL InitApplication(void)

[t.k18] {

              WNDCLASS wc;

 

              memset(&wc,0,sizeof(WNDCLASS));[t.k19] 

              wc.style = CS_HREDRAW|CS_VREDRAW |CS_DBLCLKS ;

              wc.lpfnWndProc = (WNDPROC)MainWndProc;

              wc.hInstance = hInst;

              wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

              wc.lpszClassName = "viewWndClass";

              wc.lpszMenuName = MAKEINTRESOURCE(IDMAINMENU);

              wc.hCursor = LoadCursor(NULL,IDC_ARROW);

              wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);

              if (!RegisterClass(&wc))

                            return 0;

/*@@0<-@@*/

              // ---TODO--- Call module specific initialization routines here

 

              return 1;

}

 

/*<---------------------------------------------------------------------->*/

/*@@1->@@*/

HWND CreateviewWndClassWnd(void)

[t.k20] {

              return CreateWindow("viewWndClass","view",

                            WS_MINIMIZEBOX|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZEBOX|WS_CAPTION|WS_BORDER|WS_SYSMENU|WS_THICKFRAME,

                            CW_USEDEFAULT,0,CW_USEDEFAULT,0,

                            NULL,

                            NULL,

                            hInst,

                            NULL);

[t.k21] }

/*@@1<-@@*/

/*<---------------------------------------------------------------------->*/

/* --- The following code comes from c:\lcc\lib\wizard\aboutdlg.tpl. */

BOOL _stdcall AboutDlg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)[t.k22] 

{

              switch(msg) {

                            case WM_CLOSE:

                                          EndDialog(hwnd,0);

                                          return 1;

                            case WM_COMMAND:

                                          switch (LOWORD(wParam)) {

                                                        case IDOK:[t.k23] 

                                                                      EndDialog(hwnd,1);

                                                                      return 1;

                                          }

                                          break;

              }

              return 0;

}

 

/*<---------------------------------------------------------------------->*/

/* --- The following code comes from c:\lcc\lib\wizard\defOnCmd.tpl. */

/* --- The following code comes from c:\lcc\lib\wizard\aboutcmd.tpl. */

void MainWndProc_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)[t.k24] 

{             char buffer[MAX_PATH];

 

              switch(id) {

                            // ---TODO--- Add new menu commands here

                            /*@@NEWCOMMANDS@@*/

                            case IDM_ABOUT:

                                          DialogBox(hInst,MAKEINTRESOURCE(IDD_ABOUT),

                                                        hwndMain,AboutDlg);

                                          break;

 

                            case IDM_OPEN:

                            GetFileName(buffer,sizeof(buffer));

                            break;

 

                            case IDM_EXIT:

                            PostMessage(hwnd,WM_CLOSE,0,0);

                            break;

              }

}

 

/*<---------------------------------------------------------------------->*/

/*@@2->@@*/

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)[t.k25] 

{

              switch (msg) {

/*@@3->@@*/

              case WM_SIZE:

                            SendMessage(hWndStatusbar,msg,wParam,lParam);

                            InitializeStatusBar(hWndStatusbar,1);[t.k26] 

                            break;

              case WM_MENUSELECT:

                            return MsgMenuSelect(hwnd,msg,wParam,lParam)[t.k27] ;

              case WM_COMMAND:

                            HANDLE_WM_COMMAND(hwnd,wParam,lParam,MainWndProc_OnCommand)[t.k28] ;

                            break;

              case WM_DESTROY:

                            PostQuitMessage(0);

                            break;

              default:

                            return DefWindowProc(hwnd,msg,wParam,lParam);[t.k29] 

              }

/*@@3<-@@*/

              return 0;

}

/*@@2<-@@*/

 

/*<---------------------------------------------------------------------->*/

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)[t.k30] 

{

              MSG msg;

              HANDLE hAccelTable;[t.k31] 

 

              hInst = hInstance;[t.k32] 

              if (!InitApplication())[t.k33] 

                            return 0;

              hAccelTable = LoadAccelerators(hInst,MAKEINTRESOURCE(IDACCEL));[t.k34] 

              if ((hwndMain = CreateviewWndClassWnd()) == (HWND)0)

                            return 0;

              CreateSBar(hwndMain,"Ready",1);

              ShowWindow(hwndMain,SW_SHOW);

[t.k35]       while (GetMessage(&msg,NULL,0,0)) {

                            if (!TranslateAccelerator(msg.hwnd,hAccelTable,&msg)) {

                                          TranslateMessage(&msg);

                                          DispatchMessage(&msg);

                            }

[t.k36]       }

[t.k37]       return msg.wParam;[t.k38] 

}

 

 

Download:

 

           viewer.zip          LCCでのフォルダーの内容そのままである。ショートファイルネームでアクセスできるフォルダー[1]に展開するとコンパイル可能になる。

 

 

 

使用ツール等

 

MS-OFFICE :word, 初めとしたお馴染みのツールである。著作権等は、自明であるから省く。

 

 

EPTREE.exe:       C言語の解析に使用。 出力には、編集を加えている。著作権等は、添付されたreadme.txt ファイルから抜粋。

 

*******************************************************************************

  行:エケセテネPON

  者:ふたばわに

連絡先:バグや追加してほしい機能がありましたらメールまたはHPの掲示板にカキコ

      :してください。

メール:aab87010@pop13.odn.ne.jp

HP  http://hp.vector.co.jp/authors/VA019049/

*******************************************************************************

 

 

 

End of contents.



[1] LCC で作業をしているなら、通常のプログラム・プロジェクトを置いてあるフォルダー又は、その隣など。  近藤敏郎


 [t.k1]ID+ACCEL 続いて値である。アクセラレーターの定義である。

 [t.k2]IDMenu_識別名

後は値が、続く。

 メニューコマンド定数の定義である

 [t.k3]IDAPPLICON続いて値。

 アプリケーションアイコンの定義である。

 [t.k4]あれ?

ID+S_識別名。そして、値。ストリングテーブルの定義である。

 [t.k5]ID+M_識別名。続いて値。

ステータスバーの定義である。

 [t.k6]ID+D_識別米。続いて値。

 ダイアログの定義である。

 [t.k7]ウインドウズ用の標準ヘッダーファイルと、文字処理用のヘッダーファイル。いずれも標準ヘッダーファイルである。

 [t.k8]上で表示されている、リソースハンドル用のヘッダーファイルである。

 [t.k9]インスタンス、変数。グローバル変数として定義されている。

 [t.k10]メインとなるウインドウのハンドル。グローバル変数として定義されている。

 [t.k11]単なる、プロトタイプ宣言。

 メインウインドウの、コールバック関数のみ、というのが面白いところか?

 [t.k12]ステータスバーのハンドル。ウインドウハンドルであるのと、グローバル変数として宣言されているところ。

 [t.k13]ステータスバーのアップデート関数

 [t.k14]メインウインドウのメニュードライバー関数。リソースファイルを参照のこと。

 [t.k15]ステータスバーの初期化関数

 [t.k16]ステータスバーのクリエート関数。

 [t.k17]コメントが無いが、ファイルオープンのための関数。ほぼ、そのままである。

 [t.k18]アプリケーション初期化関数。これについては、詳細を述べる。

 [t.k19]Memsetの意味と、WNDCLASS関連のマニュアルを参照のこと。

 [t.k20]メインウインドウのクリエート関数。

 [t.k21]Return(func());型の関数1つである。意見が分かれるところ、である。

 [t.k22]アバウトダイアログのコールバック関数。

 [t.k23]ジェネレーターは、バグのある出力を出す。リソースファイルを参照のこと。

 [t.k24]メインウインドウのコマンド処理関数。

 [t.k25]メインウインドウのコールバック関数。プロトタイプ宣言されていた関数である。

 [t.k26]サイズ変更に伴う、ステータスバーのアップデート、である。

 [t.k27]メニューをマウスで選択している段階、である。

 [t.k28]API,メニュー関係を参照後のこと。

 [t.k29]意見が分かれるところである。バグとハングの例も、多い。

 [t.k30]WinMain関数である。コンソールアプリケーションではmain関数に相当する。

 [t.k31]このオート変数は、初期化の前に作られ、アプリケーションの終わりまで存在している。理由を考えること。

Instanceをグローバル変数化している。

 [t.k33]メインウインドウクリエートで使うクラス登録しているだけ、である。省略も可能。

 [t.k34]あくセラーレーション、キー入力の変換テーブルの読み込みと設定。省略も可能。

 [t.k35]ステータスバーを作って、ウインドウを表示。ウインドウを表示した段階で、アプリケーションの初期が終了である。

 [t.k36]システムからのイベントメッセージを待って、アクセラレーターテーブルで変換後、処理。つまり、ここで割り込み機構を使ってコールバック関数が呼ばれる訳である

 [t.k37]メインウインドウの生成とそのチェック。アプリケーション起動のチェックともなっている。

 [t.k38]アプリケーションの返り値である。結構重要な概念。