//------------------------ // Mlib ver 3.8 // //------------------------- // 関数のプロトタイプ宣言 void Print(TCHAR*, ...); int Printf(const char*, ...); void bufprint(void); void inputbuf(TCHAR*,int); int retcheck(TCHAR*); void Font_info(TCHAR* ,long ,LONG ,BYTE ); void Line(int, int, int, int); void Rect(int, int, int, int, int); void Circle(int, int, int, int, int); void Plot_pen(int, int, int); void Clf(int); int Set_figure(int, int, int); void Text_draw(double , double , const char* ); void Plot1d_int(int* ,int) ; void Plot1d(double* ,int ); void Plotxy(double* ,double* ,int ); void Plot2d(double*,int ,int, double , double , int , int , int ); void Axis_xcap(double ,double , const char*); void Axis_ycap(double ,double , const char* ); void Aspect_ratio(double , double ); void Legend(const char* , int ); void Fig2clipboard(void); void Grid_on(int); void drawline(double, double ,double ,double ,double ,double , HPEN ,HPEN); void auto_label(double ,double ,double* ,double* ,double*); void colormap(int, COLORREF* ); int Input_int(void); double Input_double(void); TCHAR *Input_text(void); char *Input_char(void); int Get_int(int); double Get_double(int); void Get_text(int, TCHAR* ); void Get_char(int, char* ); void Set_text(int, TCHAR* ); void Set_char(int, const char* ); void Set_double(int , double); void Pause(void); void Delay(int); void Refresh(void); DWORD dialog(LPCTSTR ); LRESULT CALLBACK DialogProc(HWND , UINT , WPARAM , LPARAM ); LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM ); int main(int); // in Ver 3.8 "void main(int);" is corrected for warning // 関数のプロトタイプ宣言終了 //プログラムのメイン関数 //WIN32APIプログラムではここから始まる。 //メインウインドウとダイアログウインドウの定義 int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR lpCmdLine,int nCmdShow) { MSG msg; WNDCLASSEX winc,diaclass; hInst=hInstance; /* プロセスのハンドルを保存 */ //ウインドウクラスの定義(メインウインドウのクラスを定義している) winc.cbSize = sizeof(winc); winc.style = CS_HREDRAW | CS_VREDRAW ; //ウインドウサイズの変更可 winc.lpfnWndProc = WndProc; //ウインドウプロシージャ関数の定義 winc.cbClsExtra = 0; winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL , IDI_APPLICATION); winc.hCursor = LoadCursor(NULL , IDC_ARROW); winc.hbrBackground =(HBRUSH)(COLOR_BTNFACE+1);// (HBRUSH)GetStockObject(LTGRAY_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("GUIconsole"); //ウインドウクラスの名前。ウインドウ作成時に指定する winc.hIconSm = LoadIcon(NULL,IDI_APPLICATION); RegisterClassEx(&winc); /* ウインドウクラス登録 */ diaclass.cbSize = sizeof(winc); diaclass.style = CS_HREDRAW | CS_VREDRAW; diaclass.lpfnWndProc = DialogProc; diaclass.cbClsExtra = 0; diaclass.cbWndExtra = 0; diaclass.hInstance = hInstance; diaclass.hIcon = NULL; diaclass.hCursor = LoadCursor(NULL, IDC_ARROW); diaclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); diaclass.lpszMenuName = NULL; diaclass.lpszClassName = TEXT("CDialog"); diaclass.hIconSm = NULL; RegisterClassEx(&diaclass); /* ウインドウクラス登録 */ //メインウインドウの作成 //親ウインドウであるため、ウインドウハンドルをhWndに返すよう設定 //第一引数:ウインドウクラスの指定(上で定義したクラスを使用) //第二引数:タイトルバーの名前 //第三引数:オーバーラップ可、可視を指定(他にもいろいろある。論理和記号で結合) //第4−7引数:座標と幅、高さ hWnd = CreateWindow( TEXT("GUIconsole") , TEXT(PROGRAM_TITLE) , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT , CW_USEDEFAULT , MAINWIN_W , MAINWIN_H , NULL , NULL , hInstance , NULL ); //ディスパッチャーの処理 while(GetMessage(&msg , NULL , 0 , 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } //メインウインドウのウインドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) { HDC hdc; HGDIOBJ hpen; PAINTSTRUCT ps; long lo; long long i=0; int j,k=0; switch (msg) { case WM_DESTROY: // ウインドウcloseの処理 DeleteDC(hBuffer); DeleteObject(hBitmap); PostQuitMessage(0); return 0; case WM_CREATE: component(); //ボタン情報の登録 //プッシュボタン作成 for(i=0;i=0)&(jscr.nMin) { scr.nPos--; iVLine0--; } break; case SB_LINEDOWN: if (scr.nPos < scr.nMax){ scr.nPos++; iVLine0++; } break; case SB_PAGEUP: if (scr.nPos>scr.nMin) { if (scr.nPos>scr.nMin+DISPSIZE_H+1){ scr.nPos-=DISPSIZE_H; iVLine0-=DISPSIZE_H; } else{ scr.nPos=DISPSIZE_H-1; iVLine0=0; } } break; case SB_PAGEDOWN: if (scr.nPos < scr.nMax){ if (scr.nPos < scr.nMax-DISPSIZE_H-1){ scr.nPos+=DISPSIZE_H; iVLine0+=DISPSIZE_H; } else{ scr.nPos=iVLine; iVLine0=iVLine-DISPSIZE_H+1; } } break; case SB_THUMBPOSITION: scr.nPos = HIWORD(wp); iVLine0=(int)scr.nPos-DISPSIZE_H+1; break; } SetScrollInfo(hScroll , SB_CTL , &scr , TRUE); scr.fMask = SIF_POS; bufprint(); return 0; case WM_PAINT: //windowsのシステムでの描画命令が実行されたときの処理 //描画はメモリ内のビットマップ領域に行い //描画のたびにメモリから画面に描画データをコピーする hdc = BeginPaint(hWnd , &ps); BitBlt(hdc , sGW.x , sGW.y , sGW.w , sGW.h , hBuffer , 0 , 0 , SRCCOPY); EndPaint(hWnd , &ps); return 0; } return DefWindowProc(hWnd , msg , wp , lp); } // The specified string is displayed in MEMO window ehich is standard output for MLIB. // Instructions of string is compatible to pritnf() function; int Printf(const char *fmt, ...){ va_list args; char buf[1024]=""; TCHAR bufW[1024]=L""; int i,LN,cn=0; char bl[1024]; va_start(args ,fmt); vsprintf_s(buf,1023,fmt,args); va_end(args); LN=(int)strlen(buf); for(i=0;iBUFSIZE_W-1){ //水平文字数制限の処理.制限以上は書き込めない dum=lstrcpyn(dummy,mess,BUFSIZE_W-ml0); lstrcat(MemoBuf[ivVLine],dummy); // バッファに入力 } else{ lstrcat(MemoBuf[ivVLine],mess); // バッファに入力 } if (crflug!=0) { // 改行フラグの処理 0:改行なし  0以外:改行 iVLine++; //現在行位置をインクリメント ivVLine=iVLine%BUFSIZE_H; //余り考慮 if (iVLine>DISPSIZE_H-1) { //現在行がウインドウ幅を超えたとき iVLine0=iVLine-DISPSIZE_H+1; //表示位置をインクリメント lstrcpy(MemoBuf[ivVLine],TEXT("")); scr.cbSize = sizeof(SCROLLINFO); scr.fMask = SIF_PAGE | SIF_RANGE ; if(iVLine==ivVLine){ //現在行が表示制限行内のとき scr.nMin = DISPSIZE_H-1; scr.nMax = iVLine; } else{ //現在行が表示制限を超えたとき scr.nMin =iVLine-BUFSIZE_H+1+DISPSIZE_H; scr.nMax =iVLine; } SetScrollInfo(hScroll , SB_CTL , &scr , TRUE); scr.fMask = SIF_POS; //scr.nPos = iVLine-DISPSIZE_H+1; scr.nPos = scr.nMax; SetScrollInfo(hScroll , SB_CTL , &scr , TRUE); scr.fMask = SIF_POS; } } bufprint(); // バッファの現在ウインドウへの表示 } void bufprint(){ int i,ii; TCHAR dummy[BUFSIZE_W*DISPSIZE_H]=TEXT(""); //ダミー文字列 for(i=iVLine0;i2)){ MessageBox(hWnd, TEXT("Clf関数の引数の指定が範囲を超えています."), TEXT("Mlibによる警告"),MB_ICONHAND); return; } if(clflug<1){ // clflug=-1 指定したフィギュアウインドウの枠だけ描画 // clflug=0 指定したフィギュアウインドウの枠を描画し、枠内を消去 hpen = CreatePen(0 , 0 , RGB(0,0,0)); //黒い実線のペンの指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); //新たなペンの選択と古いペンの保存 if(clflug== CLEAR_INSIDE){ //枠内に白いブラシを指定 hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH); sFW[iID_Cfw].pn=0; } else { //枠内に透明のブラシを指定 hbrush=(HBRUSH)GetStockObject(NULL_BRUSH); } hbrush_old=(HBRUSH)SelectObject(hBuffer , hbrush); //新たなブラシの選択と古いブラシの保存 Rectangle(hBuffer,figwin_X,figwin_Y,figwin_X+figwin_W, figwin_Y+figwin_H); //枠の描画 SelectObject(hBuffer, hpen_old); //もとのペンに戻す DeleteObject(hpen); //ペンの指定解除 SelectObject(hBuffer, hbrush_old); //もとのブラシに戻す DeleteObject(hbrush); //ブラシの指定解除 } else if(clflug== CLEAR_FIG){ // clflug=1 指定したフィギュアウインドウをラベルも含めて消去 hpen = CreatePen(0 , 0 , RGB(0xff,0xff,0xff)); //白い実線のペンの指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); //新たなペンの選択と古いペンの保存 hbrush=CreateSolidBrush(RGB(0xff,0xff,0xff)); //枠内に白いブラシを指定 hbrush_old=(HBRUSH)SelectObject(hBuffer , hbrush); //新たなブラシの選択と古いブラシの保存 Rectangle(hBuffer,figwin_X-MERGIN_L,figwin_Y-MERGIN_T,figwin_X+figwin_W+MERGIN_R,figwin_Y+figwin_H+MERGIN_B); //指定したフィギュアウインドウ情報の初期化 sFW[iID_Cfw].xmin=0.; sFW[iID_Cfw].xmax=0.; sFW[iID_Cfw].ymin=0.; sFW[iID_Cfw].ymax=0.; sFW[iID_Cfw].ys=0.; sFW[iID_Cfw].xs=0.; sFW[iID_Cfw].ye=0.; sFW[iID_Cfw].xe=0.; sFW[iID_Cfw].yd=1.; sFW[iID_Cfw].xd=1.; sFW[iID_Cfw].N=0; sFW[iID_Cfw].pn=0; strcpy_s(sFW[iID_Cfw].xlabel,1,"\0"); strcpy_s(sFW[iID_Cfw].ylabel,1,"\0"); SelectObject(hBuffer, hpen_old); //もとのペンに戻す DeleteObject(hpen); //ペンの指定解除 SelectObject(hBuffer, hbrush_old); //もとのブラシに戻す DeleteObject(hbrush); //ブラシの指定解除 } else if(clflug== CLEAR_ALL){ // clflug=2 グラフィックウインドウを全て消去 hpen = CreatePen(0 , 0 , RGB(0xff,0xff,0xff)); //白いペンの指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); //新たなペンの選択と古いペンの保存 hbrush=CreateSolidBrush(RGB(0xff,0xff,0xff)); //白いブラシの指定 hbrush_old=(HBRUSH)SelectObject(hBuffer , hbrush); //新たなブラシの選択と古いブラシの保存 Rectangle(hBuffer,0,0,sGW.w, sGW.h); //フィギュアウインドウに白塗りの四角を描画 //グラフィックウインドウ情報の全消去 iID_Cfw=-1; iNum_fw=-1; for(i=0;i0){ //フィギュアウインドウに図が描画されているかどうかチェック //グローバル変数から指定フィギュアウインドウのx軸y軸の最大最小情報取得 ymax=sFW[iID_Cfw].ymax; xmax=sFW[iID_Cfw].xmax; ymin=sFW[iID_Cfw].ymin; xmin=sFW[iID_Cfw].xmin; if (grflug== ZERO_LINE){ //ゼロライン描画オン nx=0; ny=1; lx[0]=0; ly[0]=0; } if ((grflug== YGRID_LINE)|(grflug== XYGRID_LINE)){ //グリッドライン描画オン am=sFW[iID_Cfw].ys; while(am<=ymax){ ly[ny]=am; am=am+sFW[iID_Cfw].yd; ny++; } } if ((grflug== XGRID_LINE)|(grflug== XYGRID_LINE)){ am=sFW[iID_Cfw].xs; while(am<=xmax){ lx[nx]=am; am=am+sFW[iID_Cfw].xd; nx++; } } hpen = CreatePen(PS_DOT , 0 , RGB(0,0,0)); //黒い点線のペンの指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); //新たなペンの選択と古いペンの保存 SetBkMode(hBuffer , TRANSPARENT); for(j=0;j0)&(i2>0)){ if ((n>0)&(n1e-20){ //最大最小が0でないのとき auto_label(min,max,&st,&en,&in); //数値ラベルの取得 sFW[iID_Cfw].xmin=min; //グローバル変数へのフィギュアウインドウx軸最小値の書き込み sFW[iID_Cfw].xmax=max; //グローバル変数へのフィギュアウインドウx軸最大値の書き込み nobm=0; hpen = CreatePen(PS_SOLID , 0 , RGB(0,0,0)); //黒い実線のペンを指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); //ペンの設定を行い,古いペン情報をhpen_oldに Font_info(Used_Font,Used_Font_Size,0,Italic_Font_Flug); // フォントの回転設定 hFont = CreateFontIndirect( &DefFont ); // 論理フォントを作成する hFont_old=(HFONT)SelectObject( hBuffer, hFont ); //論理フォントを新たに設定し古いフォントを保存 GetTextMetrics(hBuffer , &tm); //フォントサイズ情報等取得のための設定 for(am=st;am<=max;am=am+in){ if (am*am<1e-20) am=0; sprintf_s(a,BUFNMAX,"%g",am); //数値ラベルに使う実数値をワイド文字に変換 mbstowcs_s(&nob, b, BUFNMAX, a, BUFNMAX ); //数値ラベルの文字数をnobに取得 nob--; if(nob>nobm){nobm=nob;} //数値ラベルの文字数の最大値をnobmに取得 } // 数値ラベルの間隔が数値ラベルの文字幅より大きいときの処理 if (((double)cap_W*in/(max-min))<(((double)nobm+1)*tm.tmAveCharWidth)) { in=in*2; //数値ラベルの間隔を二倍に設定 if (fabs(st)>1e-10){ //数値ラベルに0があれば0を通るように調整 char n1[BUFNMAX+1],n2[BUFNMAX+1]; sprintf_s(n1,BUFNMAX,"%g",st); sprintf_s(n2,BUFNMAX,"%g",st+in/2); if ((strlen(n1)>strlen(n2))&(fmod(fabs(st+in/2),in)<1e-10)){ st=st+in/2; } } } for(am=st;am<=max;am=am+in){ //数値ラベルの数だけループ if (am*am<1e-20) am=0; sprintf_s(a,BUFNMAX,"%g",am); mbstowcs_s(&nob, b, BUFNMAX, a, BUFNMAX ); nob--; x=cap_X+(int)(((double)cap_W-1)*(am-min)/(max-min)+.5); y=cap_Y; TextOut(hBuffer, x-(int)((double)nob*tm.tmAveCharWidth/2.), y+(int)(tm.tmHeight/6.), b, (int)nob);//数値ラベルの描画 MoveToEx(hBuffer , x , cap_Y-1 , NULL); //目盛り位置の設定 LineTo(hBuffer ,x , cap_Y-5); //目盛りの描画 } SelectObject(hBuffer , hFont_old); //元のフォントに戻す DeleteObject( hFont ); //作成した論理フォントを削除する SelectObject(hBuffer , hpen_old); //もとのペンに戻す DeleteObject(hpen); //ペンの指定解除 sFW[iID_Cfw].xs=st; //グローバル変数へのフィギュアウインドウの目盛り最小値の書き込み sFW[iID_Cfw].xe=en; //グローバル変数へのフィギュアウインドウの目盛り最大値の書き込み sFW[iID_Cfw].xd=in; //グローバル変数へのフィギュアウインドウの目盛り間隔の書き込み } Font_info(Used_Font,Used_Font_Size,0,Italic_Font_Flug); // フォントの回転設定 hFont = CreateFontIndirect( &DefFont ); // 論理フォントを作成する hFont_old=(HFONT)SelectObject( hBuffer, hFont ); //論理フォントを新たに設定し古いフォントを保存 GetTextMetrics(hBuffer , &tm); //フォントサイズ情報等取得のための設定 wsprintf(Label,L"%S",label); ms=lstrlen(Label); //キャプションの文字数 x=cap_X; y=cap_Y; TextOut(hBuffer, x-(int)(ms/2.*tm.tmAveCharWidth-cap_W/2.), y+(int)(7*(double)tm.tmHeight/6.), Label, ms);//キャプションの描画 strcpy_s(sFW[iID_Cfw].xlabel,ms+1,label); //X軸キャプションを設定 SelectObject(hBuffer , hFont_old); //元のフォントに戻す DeleteObject( hFont ); //作成した論理フォントを削除する InvalidateRect(hWnd , &d , FALSE); //システム描画命令のディスパッチ } //y軸の最小、最大設定、数値ラベル、キャプションを表示する。 //min, max : y軸の最小値、最大値 //label: y軸キャプションの文字列(100文字以内)の先頭アドレス //数値ラベルはminからmaxの間の適当な数値を自動的に計算して描画する。 //軸スケールがあらかじめ決まっているときはPlot1d()等の関数より先に呼び出す。 //未定のときはmin=max=0を指定すれば、キャプションのみを描画する。 //このときはどこで呼び出しても良い。min=max=0のとき、Plot1d等により //y軸は自動的に作成される。 //数値ラベル幅が長いとき、キャプションがウインドウ枠を飛び出すことがある。 //このときはdef.h中のMERGIN_Lを大きくするとよい。 void Axis_ycap(double min,double max, const char *label){ double am,st,en,in; int cap_X=sFW[iID_Cfw].xwin; int cap_Y=sFW[iID_Cfw].ywin; int cap_H=sFW[iID_Cfw].hwin; int x,y; size_t ms,nob,nobmax=0; HPEN hpen,hpen_old; char a[BUFNMAX+1]; TCHAR b[BUFNMAX+1],Label[100]; TEXTMETRIC tm; HFONT hFont,hFont_old; RECT d={sGW.x , sGW.y , sGW.x+sGW.w , sGW.y+sGW.h}; if ((max*max+min*min)>1e-20){ //最大最小が0以外のとき auto_label(min,max,&st,&en,&in); //数値ラベルの取得 sFW[iID_Cfw].ymin=min; //グローバル変数へのフィギュアウインドウy軸最小値の書き込み sFW[iID_Cfw].ymax=max; //グローバル変数へのフィギュアウインドウy軸最大値の書き込み hpen = CreatePen(PS_SOLID , 0 , RGB(0,0,0)); //黒い実線のペンを指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); //ペンの設定を行い,古いペン情報をhpen_oldに Font_info(Used_Font,Used_Font_Size,0,Italic_Font_Flug); // フォントの回転設定 hFont = CreateFontIndirect( &DefFont ); // 論理フォントを作成する hFont_old=(HFONT)SelectObject( hBuffer, hFont ); //論理フォントを新たに設定し古いフォントを保存 GetTextMetrics(hBuffer , &tm); //フォントサイズ情報等取得のための設定 // 数値ラベルの高さが数値ラベルの文字幅より大きいときの処理 if (((double)cap_H*in/(max-min))<5*(double)tm.tmHeight/4.) { in=in*2; //数値ラベルの間隔を二倍に設定 if (fabs(st)>1e-10){ //数値ラベルに0があれば0を通るように調整 char n1[BUFNMAX+1],n2[BUFNMAX+1]; sprintf_s(n1,BUFNMAX,"%g",st); sprintf_s(n2,BUFNMAX,"%g",st+in/2); if ((strlen(n1)>strlen(n2))&(fmod(fabs(st+in/2),in)<1e-10)){ st=st+in/2; } } } for(am=st;am<=max;am=am+in){ //数値ラベルの数だけループ if (am*am<1e-20) am=0; sprintf_s(a,BUFNMAX,"%g",am); mbstowcs_s(&nob, b, BUFNMAX, a, BUFNMAX ); nob--; x=cap_X; y=cap_Y+(int)(((double)cap_H-1)*(max-am)/(max-min)+.5); TextOut(hBuffer, x-(int)((nob+0.5)*tm.tmAveCharWidth)-4, y-(int)(tm.tmHeight/2.), b, (int)nob); //数値ラベルの描画 MoveToEx(hBuffer , cap_X, y , NULL); //目盛り位置の設定 LineTo(hBuffer , cap_X+5,y ); //目盛りの描画 if (nob>nobmax){nobmax=nob;} //y軸数値ラベルの文字数の最大値をnobmに取得 } SelectObject(hBuffer , hFont_old); //元のフォントに戻す DeleteObject( hFont ); //作成した論理フォントを削除する SelectObject(hBuffer , hpen_old); //もとのペンに戻す DeleteObject(hpen); //ペンの指定解除 sFW[iID_Cfw].nobm=nobmax; //グローバル変数へのフィギュアウインドウのy軸数値ラベル文字数の最大値書き込み sFW[iID_Cfw].ys=st; //グローバル変数へのフィギュアウインドウの目盛り最小値の書き込み sFW[iID_Cfw].ye=en; //グローバル変数へのフィギュアウインドウの目盛り最大値の書き込み sFW[iID_Cfw].yd=in; //グローバル変数へのフィギュアウインドウの目盛り間隔の書き込み } if(sFW[iID_Cfw].nobm==0){ //y軸の数値ラベルが設定されていないとき ms=strlen(label); strcpy_s(sFW[iID_Cfw].ylabel,ms+1,label); //y軸キャプションをグローバル変数に設定 } else { //y軸の数値ラベルが設定されているとき wsprintf(Label,L"%S",label); Font_info(Used_Font,Used_Font_Size,90,Italic_Font_Flug); // フォントの回転設定 hFont = CreateFontIndirect( &DefFont ); // 論理フォントを作成する hFont_old=(HFONT)SelectObject( hBuffer, hFont ); //論理フォントを新たに設定し古いフォントを保存 GetTextMetrics(hBuffer , &tm); //フォントサイズ情報等取得のための設定 ms=lstrlen(Label); //キャプションの文字数 x=cap_X; y=cap_Y; //キャプションの描画 TextOut(hBuffer, x-(int)((sFW[iID_Cfw].nobm+0.5)*tm.tmAveCharWidth+5.*(double)tm.tmHeight/4.)-4, y+(int)(cap_H/2.+(ms/2.*tm.tmAveCharWidth)), Label, (int)ms); SelectObject(hBuffer , hFont_old); //元のフォントに戻す DeleteObject( hFont ); //作成した論理フォントを削除する Font_info(Used_Font,Used_Font_Size,0,Italic_Font_Flug); // フォントの回転設定解除 } InvalidateRect(hWnd , &d , FALSE); //システム描画命令のディスパッチ } //Paste the string specified by argument ‘text’ in the figure window. // The position(x, y) is based on the coordinates of each axis in the specified figure window. // Can be used to express information such as graph titles and legends void Text_draw(double xn, double yn, const char* buf){ RECT d={sGW.x , sGW.y , sGW.x+sGW.w , sGW.y+sGW.h}; int x,y,ret; TCHAR *buf0; size_t n; HFONT hFont,hFont_old; int figwin_X=sFW[iID_Cfw].xwin; int figwin_Y=sFW[iID_Cfw].ywin; int figwin_W=sFW[iID_Cfw].wwin; int figwin_H=sFW[iID_Cfw].hwin; double ymin=sFW[iID_Cfw].ymin; //グローバル変数へのフィギュアウインドウy軸最小値の書き込み double ymax=sFW[iID_Cfw].ymax; double xmin=sFW[iID_Cfw].xmin; //グローバル変数へのフィギュアウインドウy軸最小値の書き込み double xmax=sFW[iID_Cfw].xmax; if ((sFW[iID_Cfw].ymin*sFW[iID_Cfw].ymin+sFW[iID_Cfw].ymax*sFW[iID_Cfw].ymax) +(sFW[iID_Cfw].xmin*sFW[iID_Cfw].xmin+sFW[iID_Cfw].xmax*sFW[iID_Cfw].xmax)>1e-20){ Font_info(Used_Font,Used_Font_Size,0,Italic_Font_Flug); // フォントの回転設定 hFont = CreateFontIndirect( &DefFont ); // 論理フォントを作成する hFont_old=(HFONT)SelectObject( hBuffer, hFont ); //論理フォントを新たに設定し古いフォントを保存 x=figwin_X+(int)((xn-xmin)*(figwin_W-1.)/(xmax-xmin)+.5); y=figwin_Y+(int)((ymax-yn)*(figwin_H-1.)/(ymax-ymin)+.5); n=strlen(buf)+1; buf0=(TCHAR*)malloc(n*sizeof(TCHAR)); ret=MultiByteToWideChar(0,0,buf,-1, buf0,(int)n); n=lstrlen(buf0); TextOut(hBuffer,x,y,buf0,(int)n); SelectObject(hBuffer , hFont_old); //元のフォントに戻す DeleteObject( hFont ); //作成した論理フォントを削除する InvalidateRect(hWnd , &d , FALSE); free(buf0); } } //指定されているフィギュアウインドウにint型配列ynの数値n点をグラフ化。 // 色、線の種類はPlot_pen()で指定。Axis_ycap(…)で軸の最大最小が指定 // Set_Figure()関数であらかじめフィギュアウインドウが指定されていないといけない // されていないときは、自動的に配列内の最大値最小値を探しy軸を設定、描画する。 // yn:表示すり配列の先頭アドレス(int 型) // n: 表示する配列の最大要素 void Plot1d_int(int *yn,int n){ int figwin_X=sFW[iID_Cfw].xwin; int figwin_Y=sFW[iID_Cfw].ywin; int figwin_W=sFW[iID_Cfw].wwin; int figwin_H=sFW[iID_Cfw].hwin; int i,ixx,iyy,it,ib; double x,y,xx,yy,top,btm; RECT d={sGW.x , sGW.y , sGW.x+sGW.w , sGW.y+sGW.h}; HPEN hpen,hpenull,hpen_old; double ymin,ymax; //フィギュアウインドウの最大最小が0に設定されているとき if ((sFW[iID_Cfw].ymin*sFW[iID_Cfw].ymin+sFW[iID_Cfw].ymax*sFW[iID_Cfw].ymax)<1e-20){ double ma=yn[0]; double mi=yn[0]; for(i=1;ima) {ma=yn[i];} if (yn[i]=it)&(iyy<=ib)){ //初期ペンの指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); } else { hpen_old=(HPEN)SelectObject(hBuffer , hpenull); } MoveToEx(hBuffer , ixx , iyy , NULL); SetBkMode(hBuffer , TRANSPARENT); for(i=1;iPNMAX) sFW[iID_Cfw].pn=PNMAX; SetBkMode(hBuffer , OPAQUE); SelectObject(hBuffer , hpen_old); DeleteObject(hpen); InvalidateRect(hWnd , &d , FALSE); } //指定されているフィギュアウインドウにdouble型配列ynの数値n点をグラフ化。 // 色、線の種類はPlot_pen()で指定。Axis_ycap(…)で軸の最大最小が指定 // Set_Figure()関数であらかじめフィギュアウインドウが指定されていないといけない // されていないときは、自動的に配列内の最大値最小値を探しy軸を設定、描画する。 // yn:表示すり配列の先頭アドレス(double 型) // n: 表示する配列の最大要素 void Plot1d(double *yn,int n){ int figwin_X=sFW[iID_Cfw].xwin; int figwin_Y=sFW[iID_Cfw].ywin; int figwin_W=sFW[iID_Cfw].wwin; int figwin_H=sFW[iID_Cfw].hwin; int i; int ixx,iyy,it,ib; double x,y,xx,yy,top,btm; RECT d={sGW.x , sGW.y , sGW.x+sGW.w , sGW.y+sGW.h}; HPEN hpen,hpenull,hpen_old; double ymin,ymax; //フィギュアウインドウの最大最小が0に設定されているとき if ((sFW[iID_Cfw].ymin*sFW[iID_Cfw].ymin+sFW[iID_Cfw].ymax*sFW[iID_Cfw].ymax)<1e-20){ double ma=yn[0]; double mi=yn[0]; for(i=1;ima) {ma=yn[i];} if (yn[i]=it)&(iyy<=ib)){ //初期ペンの指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); } else { hpen_old=(HPEN)SelectObject(hBuffer , hpenull); } MoveToEx(hBuffer , ixx , iyy , NULL); SetBkMode(hBuffer , TRANSPARENT); for(i=1;iPNMAX) sFW[iID_Cfw].pn=PNMAX; SetBkMode(hBuffer , OPAQUE); SelectObject(hBuffer , hpen_old); DeleteObject(hpen); InvalidateRect(hWnd , &d , FALSE); } //指定されているフィギュアウインドウにdouble型配列xnをx軸,ynをy軸に対応させたグラフを描画。 // 色、線の種類はPlot_pen()で指定。 // あらかじめAxis_ycap(…)、Axis_xcap(…)でy軸、x軸の表示範囲、軸ラベルが指定可能 // されていないときは、自動的に配列内の最大値最小値を探しy軸を設定、描画する。 // xn,yn:double型の配列 // n: 表示する配列の最大要素 void Plotxy(double *xn,double *yn,int n){ int i,ixx,iyy,it,ib,il,ir; double x,y,xx,yy,top,btm,lft,rit; RECT d={sGW.x , sGW.y , sGW.x+sGW.w , sGW.y+sGW.h}; HPEN hpen,hpenull,hpen_old; double ymin,ymax,xmax,xmin; int figwin_X=sFW[iID_Cfw].xwin; int figwin_Y=sFW[iID_Cfw].ywin; int figwin_W=sFW[iID_Cfw].wwin; int figwin_H=sFW[iID_Cfw].hwin; //フィギュアウインドウの最大最小が0に設定されているとき if ((sFW[iID_Cfw].ymin*sFW[iID_Cfw].ymin+sFW[iID_Cfw].ymax*sFW[iID_Cfw].ymax)<1e-20){ double ma=yn[0]; double mi=yn[0]; for(i=1;ima) {ma=yn[i];} if (yn[i]ma) {ma=xn[i];} if (xn[i]=it)&(iyy<=ib))){ //初期ペンの指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); } else { hpen_old=(HPEN)SelectObject(hBuffer , hpenull); } MoveToEx(hBuffer , ixx , iyy , NULL); SetBkMode(hBuffer , TRANSPARENT); for(i=1;iPNMAX) sFW[iID_Cfw].pn=PNMAX; SetBkMode(hBuffer , OPAQUE); SelectObject(hBuffer , hpen_old); DeleteObject(hpen); InvalidateRect(hWnd , &d , FALSE); } /* 指定されているフィギュアウインドウにdouble型配列ynの2D画像を描画。 配列ynは二次元データを1次元配列に並び替えたデータとして与える。x方向、y方向のポイント数はnx,nyで与えられる。 cmin,cmax: カラースケールの最小、最大値の指定,両方とも0のとき最大最小値を自動的に探す。 plflug : カラーマップの指定。0:グレースケール、1:虹色、2:青、赤の循環色 cbflug : 0:カラーバー表示off、1:カラーバー表示 szflug : 0:画像サイズに関係なくフィギュアウインドウの規定サイズに拡大して描画     1:フィギュアウインドウのサイズを正方形にして描画     2:データのサイズに対応したピクセル数で描画(最もきれい) データの縦横サイズがウインドウサイズより大きいと画像が乱れるので注意 0番目:x=0;y=0, 1番目:x=1;y=0, … ,nx番目:x=nx-1;y=0, nx+1番目:x=0;y=1, nx+2番目:x=1;y=1, … , Nx*ny-2番目:x=nx-2;y=nx-1, Nx*ny-1番目:x=nx-1;y=ny-1 の順番で二次元データを配列ynに格納する。 */ void Plot2d(double *yn,int nx,int ny, double cmin, double cmax, int plflug, int cbflug, int szflug){ int i,j,px,py; double c; int cn; HDC hdc; PAINTSTRUCT ps; COLORREF pc[PALLET_NUM]; RECT d={sGW.x , sGW.y , sGW.x+sGW.w , sGW.y+sGW.h}; int figwin_X=sFW[iID_Cfw].xwin; int figwin_Y=sFW[iID_Cfw].ywin; int figwin_W=sFW[iID_Cfw].wwin-1; int figwin_H=sFW[iID_Cfw].hwin-1; //カラーバーフラグ,サイズフラグのチェック if(cbflug== LEGEND_ON){ //カラーバーを表示 Clf(CLEAR_FIG); //フィギュアウインドウを消去し、 figwin_W=sGW.w/sFW[iID_Cfw].wn-(MERGIN_L+MERGIN_R); //新たなウインドウサイズを決定 figwin_W=(int)(figwin_W*0.85); } else{ if ((szflug== SIZE_SQUARE)|(szflug == SIZE_DATA)){ //カラーバー未表示 Clf(CLEAR_FIG); //フィギュアウインドウを消去する } } if (szflug== SIZE_SQUARE){ //描画サイズが正方形のとき if(figwin_W>figwin_H){ figwin_W=figwin_H; //横が広いとき幅を狭める } else { figwin_H=figwin_W; //縦が長いときを高さを縮める } } else if (szflug== SIZE_DATA){ //描画サイズがデータサイズのとき figwin_W=nx+1; figwin_H=ny+1; } sFW[iID_Cfw].wwin=figwin_W+1; //グローバル変数にサイズを登録し、 sFW[iID_Cfw].hwin=figwin_H+1; Clf(-1); //画面消去 //カラースケールの最小,最大値ともに0のとき自動的に最大最小値を探す. if((cmin*cmin+cmax*cmax)<1e-20){ double ma=yn[0]; double mi=yn[0]; for(i=1;ima) {ma=yn[i];} if (yn[i]figwin_W)|(ny>figwin_H)){ MessageBox(hWnd, TEXT("データのサイズがフィギュアウインドウのサイズより大きいため画像が乱れます"),TEXT("Mlibによる警告"),MB_ICONHAND); } colormap(plflug,pc); //カラーマップの取得 //2D画像の表示 for(i=0;i1) {c=1;} cn=(int)(c*((double)PALLET_NUM-1)+.5); SetPixel(hBuffer,px,py,pc[cn]); //カレントウインドウにデータサイズと同じピクセル範囲で表示 } } //カレントウインドウの図を指定のサイズに引き伸ばす hdc = BeginPaint(hWnd , &ps); SetStretchBltMode(hdc , HALFTONE); StretchBlt(hBuffer , figwin_X+1 , figwin_Y+1 , figwin_W-1 , figwin_H-1 , hBuffer , figwin_X+1 , figwin_Y+1+figwin_H-ny-1,nx,ny , SRCCOPY); EndPaint(hWnd , &ps); //////////////////// //カラーバーの表示// //////////////////// if(cbflug== LEGEND_ON){ double am,st,en,in; int i,j,l,gg,pn; double c[PALLET_NUM*5]; int x,y; size_t nob; char a[BUFNMAX+1]; TCHAR b[BUFNMAX+1]; TEXTMETRIC tm; HPEN hpen,hpen_old; HFONT hFont,hFont_old; auto_label(cmin,cmax,&st,&en,&in); //カラーラベルの取得 //Plot2Dを使ってカラーバーを表示するため一時的にフィギュアウインドウを作成 gg=iID_Cfw; iID_Cfw=FIGMAX-1; //カラーバーのサイズを決定 sFW[iID_Cfw].wwin=(int)(sFW[gg].wwin/10.); sFW[iID_Cfw].hwin=(int)(sFW[gg].hwin*0.8); sFW[iID_Cfw].xwin=(int)(sFW[gg].xwin+sFW[gg].wwin*1.03); sFW[iID_Cfw].ywin=(int)(sFW[gg].ywin+sFW[gg].hwin)-sFW[iID_Cfw].hwin; //l=(int)(sFW[gg].hwin/8.); // カラーバーのウインドウ幅 l=2; if (sFW[iID_Cfw].hwin>PALLET_NUM){ pn=PALLET_NUM-1; } else { pn=(int)(8*(floor(sFW[iID_Cfw].hwin/8.)))-1;// カラーバーの範囲を再指定 } for (i=0;i1e-10){ //数値ラベルに0があれば0を通るように調整 char n1[BUFNMAX+1],n2[BUFNMAX+1]; sprintf_s(n1,BUFNMAX,"%g",st); sprintf_s(n2,BUFNMAX,"%g",st+in/2); if ((strlen(n1)>strlen(n2))&(fmod(fabs(st+in/2),in)<1e-10)){ st=st+in/2; } } } for(am=st;am<=cmax;am=am+in){ if (am*am<1e-20) am=0; sprintf_s(a,BUFNMAX,"%g",am); mbstowcs_s(&nob, b, BUFNMAX, a, BUFNMAX ); x=sFW[iID_Cfw].xwin+sFW[iID_Cfw].wwin-1; y=sFW[iID_Cfw].ywin+(int)((sFW[iID_Cfw].hwin-1.)*(cmax-am)/(cmax-cmin)); TextOut(hBuffer, x+(int)(sFW[iID_Cfw].wwin/3.), y-(int)(tm.tmHeight/2.), b, (int)nob-1); MoveToEx(hBuffer , x-(int)(sFW[iID_Cfw].wwin/10.), y , NULL); LineTo(hBuffer , x,y ); } SelectObject(hBuffer , hFont_old); DeleteObject( hFont ); // 作成した論理フォントを削除する Font_info(Used_Font,Used_Font_Size,0,Italic_Font_Flug); // フォントサイズの縮小解除 SelectObject(hBuffer , hpen_old); DeleteObject(hpen); iID_Cfw=gg; //カレントフィギュア番号を元に戻す } sFW[iID_Cfw].N=nx*ny; InvalidateRect(hWnd , &d , FALSE); } /* If you draw continuously by using Plot() function, it will be overwritten. Legend() function displays legends for the number of the overlaid graphs. The string of the legend should be written as “line1 | line2 | line3”. The name of each line is delimited the character ‘ | ’ in the string . the legend position is specified by pos flag as 1 : upper left corner 2 : upper right corner 3 : lower left corner 4 : lower right corner 0 : bottom right outside the frame */ void Legend(const char *label, int pos){ int figwin_X=sFW[iID_Cfw].xwin; int figwin_Y=sFW[iID_Cfw].ywin; int figwin_W=sFW[iID_Cfw].wwin; int figwin_H=sFW[iID_Cfw].hwin; int lx,ly,lw,lh,lm,nobm=0; int i,ic,ll,l,pf,pw,pc,cn=0; HPEN hpen,hpen_old; HFONT hFont,hFont_old; TEXTMETRIC tm; int bufn[BUFNMAX+1]; char bl[BUFNMAX+1]; TCHAR bufW[PNMAX][BUFNMAX+1]; for(i=0;inobm){nobm=ic;} wsprintf(bufW[cn],L"%S",bl); bufn[cn]=ic; ic=0; cn++; } } pf=PenStyle; pw=PenWidth; pc=PenColor; hpen = CreatePen(PS_SOLID , 0 , RGB(0,0,0)); //黒い実線のペンを指定 hpen_old=(HPEN)SelectObject(hBuffer , hpen); //ペンの設定を行い,古いペン情報をhpen_oldに Font_info(Used_Font,Used_Font_Size,0,Italic_Font_Flug); // フォントの回転設定 hFont = CreateFontIndirect( &DefFont ); // 論理フォントを作成する hFont_old=(HFONT)SelectObject( hBuffer, hFont ); //論理フォントを新たに設定し古いフォントを保存 GetTextMetrics(hBuffer , &tm); //フォントサイズ情報等取得のための設定 ll=(nobm+1)*tm.tmAveCharWidth; // 凡例の文字の幅 lm=tm.tmAveCharWidth; // 凡例の左右上下マージン lw=lm*2+(int)(ll*2); // 凡例の幅 lh=(sFW[iID_Cfw].pn*tm.tmHeight+lm*2); // 凡例の高さ if ((pos<0)|(pos>4)){ pos=0; MessageBox(hWnd, TEXT("位置指定が間違っています.右下に表示します."),TEXT("Mlibによる警告"),MB_ICONHAND); } switch (pos){ // 凡例の表示位置決定 case 0: lx=figwin_X+figwin_W+lm; ly=figwin_Y+figwin_H-lh; break; case 1: lx=figwin_X+lm; ly=figwin_Y+lm; break; case 2: lx=figwin_X+figwin_W-lm-lw; ly=figwin_Y+lm; break; case 3: lx=figwin_X+lm; ly=figwin_Y+figwin_H-lm-lh; break; default: lx=figwin_X+figwin_W-lm-lw; ly=figwin_Y+figwin_H-lm-lh; break; } Plot_pen(0,0,7); Rect(lx,ly,lx+lw,ly+lh,1); for(i=0;i=it)&(iy<=ib)) { //yが範囲内 if ((iyy>=it)&(iyy<=ib)){ //yyが範囲内 LineTo(hBuffer ,ix,iy); } else if (iyyib){ //yyが下限より下 SelectObject(hBuffer , hpen); MoveToEx(hBuffer ,(int)(xx+(btm-yy)/(y-yy)*(x-xx)),ib,NULL); LineTo(hBuffer ,ix,iy); } } else if (iyib){ //yyが下限より下 LineTo(hBuffer ,ix,iy); } else { LineTo(hBuffer ,(int)(xx+(btm-yy)/(y-yy)*(x-xx)),ib); SelectObject(hBuffer , hpenull); } } } xx=x; yy=y; } //mlib内部関数 //ymin,ymaxから数値ラベルの初期値、最終値、間隔を自動的に計算する void auto_label(double ymin,double ymax,double *st,double *en,double *dis){ double mm,x,y,z,a,aa=1e10; double mioff,maoff; double ydis; double s[]={1.0, 2.0, 2.5, 5.0, 10.0}; int kk,k; if (ymin>ymax){ mm=ymin; ymin=ymax; ymax=mm; } if (ymin==ymax){ ymin=ymax-1e-10; } x=log10(ymax-ymin); y=floor(x); z=pow(10.,x-y); for(k=0;k<5;k++){ a=z/s[k]; if (floor(a-.1)==0){ if (aa>fabs(a-1.)) { kk=k; aa=fabs(a-1.); } } } ydis=s[kk]*pow(10.,y-1); mioff=0; maoff=0; *st=ceil((ymin-mioff)/ydis)*ydis; *en=floor((ymax+maoff)/ydis)*ydis; *dis=ydis; } /* The default figure window sizes are evenly allocated according to the number of windows determined by the Set_figure() function. The window size is changed by a specified ratio represented by (width: height) = (ax: ay) within a range that does not exceed the default size. Must be called before plot() function. */ void Aspect_ratio(double ax, double ay){ int figwin_X=(sGW.w/sFW[iID_Cfw].wn)*((sFW[iID_Cfw].nn-1)%sFW[iID_Cfw].wn)+MERGIN_L; int figwin_Y=(sGW.h/sFW[iID_Cfw].hn)*((sFW[iID_Cfw].nn-1)/sFW[iID_Cfw].wn)+MERGIN_T; int figwin_W=(sGW.w/sFW[iID_Cfw].wn)-(MERGIN_L+MERGIN_R)+1; int figwin_H=(sGW.h/sFW[iID_Cfw].hn)-(MERGIN_T+MERGIN_B)+1; int fW,fH; if (sFW[iID_Cfw].N==0) Clf(1); fW=(int)(figwin_H*ax/ay+.5); fH=(int)(figwin_W*ay/ax+.5); if(figwin_W>fW){ //figwin_X=figwin_X+(figwin_W-fW)/2; figwin_W=fW; //横が広いとき幅を狭める } else if (figwin_H>fH){ figwin_Y=figwin_Y+(figwin_H-fH)/2; figwin_H=fH; //縦が長いときを高さを縮める } sFW[iID_Cfw].wwin=figwin_W; sFW[iID_Cfw].hwin=figwin_H; sFW[iID_Cfw].xwin=figwin_X; sFW[iID_Cfw].ywin=figwin_Y; //フィギュアウインドウの枠内消去 Clf(-1); } // グラフィックウインドウ全体をクリップボードにコピーする void Fig2clipboard(){ TCHAR buf[1024]; HANDLE hdl; OpenClipboard(hWnd); EmptyClipboard(); //クリップボードをクリア hdl=SetClipboardData(CF_BITMAP, hBitmap); //クリップボードに取り込む CloseClipboard(); if(hdl==NULL){ MessageBox(hWnd, TEXT("図のクリップボードへのコピーに失敗しました."), TEXT("Mlibによる警告"),MB_ICONHAND); } else { wsprintf(buf, TEXT("図がクリップボードにコピーされました。")); MessageBox(hWnd, buf, TEXT("Mlibによる警告"), MB_ICONHAND); } } //mlib内部関数 // Plot2Dで用いるカラーマップを配列pcに入れて戻す。Plot2Dから呼び出している。 // plflug=0 グレイスケール // plflug=1 レインボーカラー // plflug=2 黒-青-白-赤-黒の循環色(位相の表示などに便利) void colormap(int plflug, COLORREF *pc){ int i,p1,p2,p3,p4,p5; BYTE r,g,b,f; BYTE pc0[3*PALLET_NUM/2]; if ((plflug<0)|(plflug>2)){ plflug=1; MessageBox(hWnd, TEXT("カラーパレットの指定が範囲を超えています"),TEXT("Mlibによる警告"),MB_ICONHAND); } switch(plflug){ case GRAY: //グレイスケール for(i=0;i=0)&(i=0)&(i=0)&(i=0)&(i=0)&(i=0)&(i=0)&(i