M7第3話 水平線作図

以前、ニフティのFAフォーラムで知り合った方に会った時、たまたま、会社で使用されているEWSのCAD/CAMシステムを見せてもらった事がある。そのソフトは、補助線を片っ端から引きまくって、補助線上をトレースして作図する、というのが主体のソフトだった。へぇ〜こういうソフトもあるんだなぁ〜。もう12年も昔の話だけど。で、さっそく、うちのDOS版CADモドキにも、補助線を作図しまくるオプションってのを作った。一部で、これはこれで結構ウケていたらしい。勿論、別のCADでは、基本的に補助線を引かせないようにして作図する、というソフトもあった。まぁそれはいいとして。。。
その前段階として、まずは、用紙一杯に水平線を作図する機能を作る事にしよう。
 

 
パターンとしては、
  @通過点の指定(通過点座標の入力)
  A用紙サイズを取得
  B通過点を通り、用紙の左端から用紙の右端までの水平線を作図
   線分の、始点のX座標は用紙の左端、終点のX座標は用紙の右端、
   線分の、始点・終点のY座標は、通過点のY座標
   を取ればいいです
ってな具合でしょう。
 

 
で問題は、用紙サイズを取得する方法。これは、M7dev v3.04で、
用紙サイズを取得します。
#include <m7.h>
void m7GetPaperSize(DPOINT psize[2]);
psize 用紙サイズを格納するポインタを指定します。
本関数を呼び出した後、この変数は以下の値を返します。
psize[0] 作図原点[mm単位]
psize[1] 用紙の幅・高さ[mm単位]
備考 用紙レイアウトが縦の場合は幅と高さを入換えて解釈してください。
を追加して頂きましたので〜、これが使えます。んがしかし、座標値は実寸法で扱いますので、尺度(スケール)を考慮してやる必要があります。で、下記の関数が使えます。まぁ有り得ないとは思いますが、変な値にならないよう、返り値が 0 や負の値の場合には強制的に、1 を返す(スケール=1にする)ようにします。
現在のスケールを取得します。
#include <m7.h>
double m7GetCurrentScale(void)
また、用紙レイアウトが横か縦かを判別する必要がありますので、下記の関数を使って返される変数の値loutを見て判断する必要があります。ポインタを指定せねばならない点に注意します。typeの方は今回関係無いです。
用紙タイプを取得します。
#include <m7.h>
void m7GetPaperType(BYTE *lout, BYTE *type);
lout 用紙レイアウトを格納するポインタを指定します。
本関数を呼び出した後、この変数は以下の値を返します。
 0: 横レイアウト
 1: 縦レイアウト
type用紙タイプを格納するポインタを指定します。
 
そういう訳で今回のプログラムは、↓ こんな感じ〜
 
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <m7.h>
 
/*
 単に、水平線を描いてみる
    by AF
*/
 
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];
 BYTE pplout,pptype;
 DPOINT psize[2];
 double cscale ;
 
 m7GetPaperType(&pplout,&pptype);
 m7GetPaperSize(psize);
 cscale = m7GetCurrentScale() ;
 if (cscale <= 0.0) {
  cscale = 1.0 ;
 }
 
 switch (wParam){
 case IDC_BUTTON1:
  m7GetItemValues(hwnd, IDC_EDIT1, x, 1);
  m7GetItemValues(hwnd, IDC_EDIT2, y, 1);
  if (pplout == 0) {
   lpos[0].x = psize[0].x / cscale ;
   lpos[0].y = y[0] ;
   lpos[1].x = (psize[0].x + psize[1].x) / cscale ;
   lpos[1].y = y[0] ;
  }
  else {
   lpos[0].x = psize[0].y / cscale ;
   lpos[0].y = y[0] ;
   lpos[1].x = (psize[0].y + psize[1].y) / cscale ;
   lpos[1].y = y[0] ;
  }
  m7StepObject();
  m7MakeLineObject(lpos, M7OBJ_NORMAL);
  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){
 /*
  ** ここにメソッドの初期化に関する式を記入します。
  */
 m7SetProc(PROC_GETPOS);
 m7StatusText("通過点を指定して下さい", M7STS_NORMAL);
 return 0;
}
 
/********************************************/
/* ON_CLICKメッセージハンドラ */
/********************************************/
int on_click(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにマウスクリックに関する式を記入します。
  */
 DPOINT pos;   // クリックした位置
 BYTE pplout,pptype;
 DPOINT psize[2];
 double cscale ;
 
 m7GetPaperType(&pplout,&pptype);
 m7GetPaperSize(psize);
 cscale = m7GetCurrentScale() ;
 if (cscale <= 0.0) {
  cscale = 1.0 ;
 }
 pos = *(LPDPOINT)lParam; // lParamに位置が入っているので変数posに代入
 if (pplout == 0) {
  lpos[0].x = psize[0].x / cscale ;
  lpos[0].y = pos.y ;
  lpos[1].x = (psize[0].x + psize[1].x) / cscale ;
  lpos[1].y = pos.y ;
 }
 else {
  lpos[0].x = psize[0].y / cscale ;
  lpos[0].y = pos.y ;
  lpos[1].x = (psize[0].y + psize[1].y) / cscale ;
  lpos[1].y = pos.y ;
 }
 m7StepObject();
 m7MakeLineObject(lpos, M7OBJ_NORMAL);
 return 0;
}
 
/********************************************/
/* ON_MOUSEMOVEメッセージハンドラ */
/********************************************/
int on_mousemove(HWND hwnd, int message, WPARAM wParam, LPARAM lParam){
 /*
  ** ここにマウスカーソル移動時の式を記入します。
  */
 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);
}
 
 
C言語ソースファイルとアイコンBMPファイルを用意したら、「M7dev」で開いて、「ビルド」≫「ビルド」を行って、「ビルドは正常終了しました」と表示されたらOKです。「〜.m7p」というファイルが作成されます。これを「部品呼び出し」してみて下さい。