M7第2話 座標値入力での2点指定線分

私はずっと機械系のCADを使っているせいか、座標指定の際、座標値を入力出来るのが当たり前という感覚がある。座標値入力がある、という事は、原点(0,0)があるという事。プロッタやNC等のホームポジション、図面、図形の原点(基準点)、そういうのは常に意識してた。しかしだー。汎用といいつつも実際には建築系らしい?「Jw_cad」や「M7」等では、余り原点&座標値入力、という感覚が表に見えないので、ちょっとしたカルチャーショックだった。(笑)
そういう訳で、前回のプログラムをいじって、座標値入力が出来る2点指示の線分作図コマンドを作ってみることにするー。(自爆)
 

 
前回は「M7dev」そのもので作業をしていたけれど、今後は、テキストエディタでプログラムを書いて、グラフィックソフトでアイコンを描いて、で、「M7dev」で開いて『ビルド』を行い、修正等はやはり、テキストエディタ・グラフィックソフトを使う事にしています。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <m7.h>
 
/*
  単に、座標で線を描いてみる
    by AF
*/
 
int smode ;     /* Step Mode 0:始点指定 1:終点指定 */
DPOINT lpos[2] ;  /* 始点座標、終点座標 */
 
/********************************************/
/* ON_INITDLGメッセージハンドラ */
/********************************************/
int on_initdlg(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにダイアログの初期化に関する式を記入します。
  */
 m7CreateItem(hwnd, ITEM_STATIC , 0     , 10, "X(&X)", 0);
 m7CreateItem(hwnd, ITEM_EDIT  , IDC_EDIT1 , 30, ""   , 40);
 m7CreateItem(hwnd, ITEM_STATIC , 0     , 80, "Y(&Y)", 0);
 m7CreateItem(hwnd, ITEM_EDIT  , IDC_EDIT2 , 100, ""   , 40);
 m7CreateItem(hwnd, ITEM_BUTTON , IDC_BUTTON1, 150, "Go(&G)",30);
 return 0;
}
 
/********************************************/
/* ON_COMMANDメッセージハンドラ */
/********************************************/
int on_command(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにON_COMMANDメッセージの応答式を記入します。
  */
 double x[1];
 double y[1];
 
 switch (wParam){
 case IDC_BUTTON1:
  m7GetItemValues(hwnd, IDC_EDIT1, x, 1);
  m7GetItemValues(hwnd, IDC_EDIT2, y, 1);
  switch(smode) {
  case 0:
   lpos[0].x = x[0];
   lpos[0].y = y[0];
   m7StatusText("終点を指定して下さい", M7STS_NORMAL);
   smode = 1;
   break;
  case 1:
   lpos[1].x = x[0];
   lpos[1].y = y[0];
   m7StepObject();
   m7MakeLineObject(lpos, M7OBJ_NORMAL);
   m7StatusText("始点を指定して下さい", M7STS_NORMAL);
   smode = 0;
   break;
  }
  break;
 }
 return 0;
}
 
/********************************************/
/* ON_CLOSEDLGメッセージハンドラ */
/********************************************/
int on_closedlg(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにダイアログの終了化に関する式を記入します。
  */
 return 0;
}
 
/********************************************/
/* ON_INITWNDメッセージハンドラ */
/********************************************/
int on_initwnd(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにメソッドの初期化に関する式を記入します。
  */
 smode = 0;
 m7SetProc(PROC_GETPOS);
 m7StatusText("始点を指定して下さい", M7STS_NORMAL);
 return 0;
}
 
/********************************************/
/* ON_CLICKメッセージハンドラ */
/********************************************/
int on_click(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにマウスクリックに関する式を記入します。
  */
 DPOINT pos;  // クリックした位置
 pos = *(LPDPOINT)lParam; // lParamに位置が入っているので変数posに代入
 switch(smode) {
 case 0:   // 始点処理→終点処理へ
  lpos[0] = pos ;
  m7StatusText("終点を指定して下さい", M7STS_NORMAL);
  smode = 1;
  break;
 case 1:   // 終点処理→線分作図→始点処理へ
  lpos[1] = pos ;
  m7StepObject();
  m7MakeLineObject(lpos, M7OBJ_NORMAL);
  m7StatusText("始点を指定して下さい", M7STS_NORMAL);
  smode = 0;
  break;
 }
 return 0;
}
 
/********************************************/
/* ON_MOUSEMOVEメッセージハンドラ */
/********************************************/
int on_mousemove(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにマウスカーソル移動時の式を記入します。
  */
 DPOINT pos[2]; // クリックした位置
 switch(smode) {
 case 1: // 終点を指定しようとしている時:エコー表示
  pos[0] = lpos[0] ;
  pos[1] = *(LPDPOINT)lParam;
  m7DrawLine(pos);
  break;
 }
 return 0;
}
 
/********************************************/
/* ON_UNDOメッセージハンドラ */
/********************************************/
int on_undo(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにアンドゥに関する式を記入します。
  */
 m7UndoObject();
 return 0;
}
 
/********************************************/
/* ON_NOTIFYメッセージハンドラ */
/********************************************/
int on_notify(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここに通知メッセージに関するコードを記入します。
  */
 return 0;
}
 
/********************************************/
/* ON_CLOSEWNDメッセージハンドラ */
/********************************************/
int on_closewnd(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
 ** ここにメソッドの終了化に関する式を記入します。
  */
 return 0;
}
 
/********************************************/
/* dialog proc 基本的に変更しません */
/********************************************/
int dlgproc(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 
 switch (message){
 case ON_INITDLG:
  return on_initdlg(hwnd, message, wParam, lParam);
 case ON_COMMAND:
  return on_command(hwnd, message, wParam, lParam);
 case ON_CLOSEDLG:
  return on_closedlg(hwnd, message, wParam, lParam);
 }
 return 0;
}
 
/********************************************/
/* window proc 基本的に変更しません */
/********************************************/
int wndproc(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 switch (message){
 case ON_INITWND:
  return on_initwnd(hwnd, message, wParam, lParam);
 case ON_CLICK:
  return on_click(hwnd, message, wParam, lParam);
 case ON_MOUSEMOVE:
  return on_mousemove(hwnd, message, wParam, lParam);
 case ON_UNDO:
  return on_undo(hwnd, message, wParam, lParam);
 case ON_NOTIFY:
  return on_notify(hwnd, message, wParam, lParam);
 case ON_CLOSEWND:
  return on_closewnd(hwnd, message, wParam, lParam);
 }
 return 0;
}
 
/********************************************/
/* main 基本的に変更しません */
/********************************************/
void main(void){
 m7DispatchProc(dlgproc, wndproc);
}
 
ダイアログ初期化用のメッセージハンドラ ON_INITDLG内に、ダイアログに表示したい内容を以下のように記述しています。
  m7CreateItem(hwnd, ITEM_STATIC , 0     , 10, "X(&X)", 0);
  m7CreateItem(hwnd, ITEM_EDIT  , IDC_EDIT1 , 30, ""   , 40);
  m7CreateItem(hwnd, ITEM_STATIC , 0     , 80, "Y(&Y)", 0);
  m7CreateItem(hwnd, ITEM_EDIT  , IDC_EDIT2 , 100, ""   , 40);
  m7CreateItem(hwnd, ITEM_BUTTON , IDC_BUTTON1, 150, "Go(&G)",30);
ITEM_STATICは、文字を表示します。
ITEM_EDITは、入力ボックスを表示します。
ITEM_BUTTONは、ボタンを表示します。
その他の引数では、位置、大きさ、内容、を示しています。IDC〜は、後で、どの入力ボックスの内容なのか、どのボタンを押したのか、等を判断したりするのに利用する識別子となります。
 
で、ON_COMMANDメッセージハンドラを記述します。ラジオボタンを押した時、チェックボタンを押した時、リストを選択した時、ボタンを押した時、の処理を記述します。これにより、コマンド内容を変更したり、コマンドのパラメータを変えたりします。ここでは、
 switch (wParam){
 case IDC_BUTTON1:
  ・・・(ボタンを押した時の処理)・・・
 }
を行っています。
「m7GetItemValues(hwnd, IDC_EDIT1, x, 1);」で、入力ボックスの内容を変数 x に入れています。何故、「double x[1];」と宣言しているのかというと、この入力ボックスでは元々、カンマで区切られた複数の実数値、を扱えるようになっているから、なのですが、ここでは、1つの数値しか入力しませんので、このようにしています。
 
とまぁそういう訳で、ボタンを押した時も、マウスで指定した時と同じように、始点・終点の指定をしたら線分を描かせる、という風にプログラミングします。
 

 
次にアイコンですが、私はP&A社の「PaintShopPro6」をよく利用しているので、これを使います。新規作成で、64×64ドット・16色で作成し、絵を描いて、Windows Bitmapファイルを作成しますが、色の扱いに注意をする必要があるでしょう。ヘルプによると、
黒 :背景色  濃赤:ペン1  白 :ペン2  濃黄:ペン3
濃青:ペン4  濃紫:ペン5  濃水:ペン6  明灰:ペン7
暗灰:補助色  赤 :淡表示  緑 :エコー1 黄 :エコー2
で描く事になっているようです。
ファイル名は、C言語ソースファイルと同じ名前で拡張子が違うようにします。
 

 
C言語ソースファイルとアイコンBMPファイルを用意したら、「M7dev」で開いて、「ビルド」≫「ビルド」を行って、「ビルドは正常終了しました」と表示されたらOKです。「〜.m7p」というファイルが作成されます。これを「部品呼び出し」してみて下さい。