2016年8月30日星期二

[Mstn PureMDL] mdlWindow_setFunction  捕捉打开窗口的变化

MdlFunctionP      mdlWindow_setFunction
(
int      type ,
MdlFunctionP      function
);
type :
The type parameter sets which type of mdlWindow_... notification function is being set by the call to mdlWindow_setFunction. This parameter can be either WINDOW_MODIFYEVENTS (window is shown on the screen or hidden, size changes, or stacking order changes) or WINDOW_SCROLLEVENTS (window's contents are scrolled).


 WINDOW_MODIFYEVENTS : ウインドウが画面上に表示または非表示の変更、サイズ変更、など。
WINDOW_SCROLLEVENTS :ウィンドウの内容がスクロールされる


例文を見てみましょう。


要望:ウインドウで表示しているViewにより、DropLiast中に選択できるViewも変更できるようにする。
何と言いたいのは、以下の図を見てくださいね。

ActiveしているViewは1だけので、選択肢に1だけを活性してます。
 

もし、1,2,4のViewがActiveになっていて、選択肢に1,2,4を選択できるよになります。
 
========================================================================
Src Codeをざっくりと説明します。
①ダイアログをOpenして、Startするとき、いかのMDLの処理を追加してください。

Private void cmdSTART(void)            
cmdNumber CMD_LIUBINTEST_START
{
 mdlState_startPrimitive(NULL,NULL,1,1);
 mdlState_setFunction(STATE_COMMAND_CLEANUP, cleanup);
 mdlWindow_setFunction(WINDOW_MODIFYEVENTS, windowModifyFunc);
 EnableSet();
 mdlInput_sendKeyin("LIUBINTEST SCAN", 0, INPUTQ_EOQ, NULL);
}

② windowModifyFuncを説明いたします。
Private void windowModifyFunc
(
MSWindow   *window,    /* => window that event applies to */
int     eventType,        /* => type of event */
BSIRect    *oldGlobalP    /* => old global rectangle */
)
{ int viewNo;
 if (mdlWindow_isView(&viewNo,(MSWindow *)window)
   && (eventType == WINDOW_SHOWEVENT ||
    eventType == WINDOW_ORDEREVENT ||
     eventType == WINDOW_HIDEEVENT  ||
      eventType==WINDOW_MINIMIZEEVENT))
 { _viewNo = viewNo;
  _eventType = eventType;
  mdlDialog_cmdNumberQueue(TRUE, CMD_LIUBINTEST_VIEW, NULL, TRUE);
 }
 return;
}

eventType :Windowのイベントです。表示、順番変更、非表示、最小限などですね。

③ CMD_LIUBINTEST_VIEWのロジックです。

Private void cmdView(void)             /*
=====================================================================================*/
cmdNumber CMD_LIUBINTEST_VIEW
{
 DialogItem *diP;
 int   ic, sic;
 { if (mdlView_isActive(_viewNo)) →Activeかどうか判断
  { 
   // これはリストの表示制御です。
   // _OptionrawItemP 引数は④で紹介します。
   mdlDialog_optionButtonSetEnabled(_OptionrawItemP, _viewNo, TRUE);
  }
  else if (_eventType == WINDOW_ORDEREVENT || _eventType == WINDOW_HIDEEVENT || _eventType ==     WINDOW_MINIMIZEEVENT)
  { mdlDialog_optionButtonSetEnabled(_OptionrawItemP, _viewNo, FALSE);
   if (_u40Sleeve2CSVDlg.View == _viewNo)
   { for (ic = 0, sic = -1; ic < _viewNo; ic++)
    { if(mdlView_isActive(ic)) sic = ic;
    }
    if (sic != -1) _uLiuBinTestDlg.View = sic;
    else
    { for (ic = _viewNo; ic < MAX_VIEWS; ic++)
     { if(mdlView_isActive(ic)) sic = ic;
     }
     if (sic != -1) _uLiuBinTestDlg.View = sic;
     else  return;
    }
   }
   if (diP = mdlDialog_itemGetByTypeAndId(mdlDialog_getToolSettings(), RTYPE_OptionButton, OPTIONBUTTONID_LIUBINTEST_VIEW, 0))
    mdlDialog_itemSynch(mdlDialog_getToolSettings(), diP->itemIndex);
  }
 }
}

④_OptionrawItemP 引数を紹介します。

この変数はOptionボタンの項目ですね。Hook関数に書いています。
Private void optionHook(DialogItemMessage *dimP)        /*
================================================================================ */
{ int i;
 dimP->msgUnderstood = TRUE;
 switch (dimP->messageType)
 {
  case DITEM_MESSAGE_CREATE:  /*
  -------------------------------- */
   break;
  case DITEM_MESSAGE_INIT:     /*
  --------------------------------------------*/
   _u40Sleeve2CSVDlg.View = -1;
   for(i=0;i   { mdlDialog_optionButtonSetEnabled(dimP->dialogItemP->rawItemP,i,mdlView_isActive(i));
    _OptionrawItemP = dimP->dialogItemP->rawItemP;
   }
   if(mdlView_isActive(tcb->lstvw))
   { _uLiuBinTestDlg.View = i;
   }
   else
   { for(i=0;i    { if(mdlView_isActive(i))
     { _uLiuBinTestDlg.View = i;
      break;
     }
    }
   }
   break;
  case DITEM_MESSAGE_SETSTATE:
   break;
  case DITEM_MESSAGE_STATECHANGED:
   if( dimP->u.stateChanged.reallyChanged )
   { mdlInput_sendKeyin("LIUBINTESTSCAN", 0, INPUTQ_EOQ, NULL);
   }
   break;
  case DITEM_MESSAGE_RELOADDATA:
   break;
  case DITEM_MESSAGE_DESTROY: 
   break;
  default:    
   dimP->msgUnderstood = FALSE;
   break;
 }
}
⑤OPTIONBUTTONID_LIUBINTEST_VIEW
   これはDlg中のOPTIONBUTTONIDです。IDです。識別子ですね。





以上の処理を付ければ、要望を実現することができると思います。

メモです。







2016年8月28日星期日

mdlDialog_cmdNumberQueue

mdlDialog_cmdNumberQueue


今日はこの関数を使っている時、引数の意味を調べました。
void      mdlDialog_cmdNumberQueue
(
BoolInt      localCmd ,
long      cmdnum ,
char*      unparsedP ,
BoolInt      atEndOfQueue
);


localCmd : 呼び出し元のコマンドからの物の場合、このパラメータをTRUEに設定しなければならないです。そうでなければ、(FALSEの場合)コマンドはMstnコマンドテーブルからのものである
と仮定されます。
cmdnum   コマンド番号です。 キューに入れたいコマンドです。
unparsedP
atEndOfQueue  コマンドが入力キューの最後に配置される場合、パラメータがTRUEに設定されるべきです。それ以外の場合は、入力キューの先頭に配置されます。


自分で作った例文:
Private void cmdCANCEL(void)             /*
// これは「終了」ボタンーを押して、現在のAPPをアンロードします。
// CMD_MDL_SILENTUNLOAD Mstn中で定義しているコマンドですので、FALSEに設定してる。
================================================================================ */
cmdNumber CMD_U40SLEEVE2CSV_CANCEL
{ if(_settings.t.TRACE) printf("[U40Sleeve2CSV] cmdCANCEL -I- CMD_U40SLEEVE2CSV_CANCEL\n");
 mdlDialog_cmdNumberQueue(FALSE,CMD_MDL_SILENTUNLOAD,mdlSystem_getCurrTaskID(),TRUE);
 return;
}




Private void cmdBACK(void)             /*
// この関数はサブダイアログからメイン画面へ戻る。
// CMD_LIUBINTESTAPP_START 自分で定義しているコマンドですので、TRUEに設定してる。
================================================================================ */
cmdNumber CMD_U40SLEEVE2CSV_BACK
{
 if(_settings.t.TRACE) printf("[U40Sleeve2CSV] cmdBACK -I- CMD_U40SLEEVE2CSV_BACK\n");
 /*--------------------------------------------------------------------------*/
 /* mainダイアログへ遷移             */
 /*--------------------------------------------------------------------------*/
 mdlDialog_cmdNumberQueue(TRUE, CMD_LIUBINTESTAPP_START ,mdlSystem_getCurrTaskID(), TRUE);

 return;
}


メモします。
何か不正の場合、是非指摘してくれてくださいね。



2016年8月25日星期四

Mstn MDL 「表示」と言う文字を文字化けしました

文字化けについて

  • シフトJISコードで「表示」という文字を、CGIスクリプト中に記述して出力すると「侮ヲ」と文字化けします。
  • 「侮」という文字から、何だかコンピュータに馬鹿にされている気持ちになったりもします。
  • どうしてこのように文字化けしてしまうのでしょうか? このコーナではそんな文字化けについて考察してみます。
  • まず日本語文字コードの基礎知識として、大きく以下のようなコードが存在することを理解しておきましょう。
    文字コード摘要
    JISコードJIS規格のX0208で定められた文字集合。7ビットコード2文字で日本語文字を表現します。メールで使用する代表的な文字コード。
    EUCコード日本語UNIX環境で使用される文字コード。8ビットコードで表現されます。
    シフトJISコードMicrosoft社が決めたコードで、主にパソコンを基盤に、WindowsやMacで使用されます。8ビット領域も使用します。
    Unicodeすべての文字を2バイトで表し、世界中の文字を表現しようとしています。

  • KENT WEBではCGIスクリプトは「シフトJISコード」で記述しています。
  • 本当は文字化けや正規表現処理などを考慮するとEUCコードで書く方が都合がよく、もし自分のためだけに使用するCGIスクリプトであるならば、迷わずEUCコードで記述することでしょう。
  • ここでさきほど述べたシフトJISの「表示」という文字コードは以下のとおりです。
    文字表示
    シフトJISコード955C8EA6

  • ここで都合の悪いことが発生します。実は、「表」の2バイト目の「5C」に問題があるのです。
  • つまり、「5C」とはメタ文字(特殊文字)の「\」を表すからです。
  • 「\」が文字列中にあると、それはエスケープ記号として単に取り去られてしまいます。
  • したがって、「表示」という文字をCGIが出力するときには以下のように展開してしまいます。
    (1) 95 5C 8E A6 .... 記述時点
    (2) 95    8E A6 .... 「5C」を「\」と解釈し取り去る(その次の8Eをエスケープすると解釈)
    (3) 95 8E A6    .... 展開結果
    

  • このようにして、展開結果は以下のようなコードで出力されることになります。
    文字侮ヲ (半角)
    シフトJISコード958EA6

  • このような文字化けを防止するには以下のような方法があります。
    1. 「表」のようなメタ文字を含む文字には、後にエスケープ記号「\」を付ける。

      例 : print "表\示";

      理由 : 「表 + \」という文字コードで 95 5C 5C となり、中央の 5C が次の 5C をエスケープ展開し、結果として 95 5C として出力される。

    2. ダブルクオーテーションマーク「"」で囲まずに、シングルクオーテーションマーク「'」を使用する。

      例 : print '表示';

      理由 : シングルクオーテーション「'」内では文法上「展開」処理をしないため、文字コードの 95 5C はそのまま解釈されて出力される。

  • 「表」のように2バイト目に「5C」のコードが使われている文字は以下のとおりです。
    *これらの文字を使用する際は「表」に対する対処法とまったく同じです。
    ―ソЫⅨ噂浬欺圭構蚕十申曾箪貼能表暴予禄
    兔喀媾彌拿杤歃濬畚秉綵臀藹觸軆鐔饅鷭偆砡

  • 【注意】ただし、この文字化け文字(2バイト目に 5C が来る文字)をエスケープしない状態で「ダブルクオーテーション」又は「シングルクオーテーション」の中で末尾に使う場合には文字化けとはならずに Perlが「文法エラー」となってしまうので、特に注意が必要です。
    この場合の対処方法は前掲と同じで直後にエスケープ記号「\」を付加します。
    悪い例1 : $title = "計画表"; → サーバエラー(文法エラーとなる)
    悪い例2 : $title = '計画表'; → サーバエラー(文法エラーとなる)

    良い例1 : $title = "計画表\";
    良い例2 : $title = '計画表\';
    ★以上の文章以下のurlから:
     http://www.kent-web.com/pubc/jcode/