プログラムtips


プログラム全般

●constにまつわる話

int const *a;(const int *a という書き方もあり)
は*a = 50ができない
int * const b = &c;
は、b = &dができない。
「その変数が変更不能であることを示す const は、基本的に型名の後ろに書 く」という法則があるらしい。


c++インスタンス
MyClass a(10);
MyClass *a = new MyClass(10);


●エラーメッセージ LNK2001
関数のプロトタイプしか宣言していない時にこのようなエラーが発生する。
関数を作成する際にクラス解決演算子がついていない場合にも生じる。
エラーについては
http://www.nitoyon.com/vc/reference/error.htm
が詳しいので参照すること。


●関数が大きくなることのデメリット
変数の有効範囲が大きくなり、初期化が行われているか、どのように使われているか等をチェックするのに時間がかかる。

詳細な実装を読む必要が出てくるため、処理の流れを理解するのに時間がかかる。

処理が細かく分割されていないので新しい機能を追加することが困難になる。


VB6.0
●高速化
Switch文の処理は配列を用いた処理に置き換えることができる場合がある。
配列を用いると分岐処理を行わずに済み、処理の高速化が行える。


●グリッド登録の際の高速化
データの追加はTextMatrixのほうがAddItemより高速に行える。
このとき、AddItemはデータをグリッドの先頭に追加し、以降のデータを一行ずつずらす作業が行われる。
TextMatrixでこのような処理が行いたければソートする必要がある。


●VB6.0のコマンドボタンは文字色を変えられない。
ボタンの文字色を変えたい時はチェックボックスを用いる。
チェックボックスはプロパティを変更する事で概観をコマンドボタンのように変えられる。


●MSchartの印刷
クリップボード経由でPrinterオブジェクトを使用して印刷を行なう。
メインの処理は以下のようになる。

'クリップボードにコピー
MSChart1.EditCopy
'クリップボード内のイメージを読込
Set tmpPic = Clipboard.GetData()
'指定位置に印刷する。
Printer.PaintPicture tmpPic, Printer.CurrentX, Printer.CurrentY
Printer.CurrentY = Printer.CurrentY + (tmpPic.Height * 567 / 1000)

また、以下のページを参考にするとよい。



●VB6.0の印刷プレビュー
FormやPictureを用いてForm1.Print,Picture1.Printとすることで、 対象となるFormやPictureにプレビューが表示できる。
以下のページを参考にすること。
http://hpcgi1.nifty.com/MADIA/VBBBS/wwwlng.cgi?print+200502/05020079.txt

●VB6.0での定数の使用(Cでの#defineの代わりに用いるもの)
Constを用いる。
定数にそのまま数字を用いると、プログラム修正時に時間がかかるのでやめる事。


●VB6.0でクリックボードを使用する。
Clipboard.SetTextで登録。
Clipboard.GetTextで取得。

●MsChartを使ってツールチップテキストを表示する方法

'グラフにマウスカーソルを合わせた時にツールチップテキストを表示する。
Private Sub MSChart1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    
    Dim Part As Integer
    Dim Idx1 As Integer '系列(横)
    Dim Idx2 As Integer 'データポイント(縦)
    Dim Idx3 As Integer
    Dim Idx4 As Integer
    
    Dim value As Double, nullflag As Integer
    Dim labelX As String

    With MSChart1
        'マウスがある位置に何が存在するかを調べる
        .TwipsToChartPart X, Y, Part, Idx1, Idx2, Idx3, Idx4
        
        'マウスがデータポイントを示していた時。
        If (Part = VtChPartTypePoint) Then
            'データグリッドに存在する値を取得する。
            .DataGrid.GetData Idx2, Idx1, value, nullflag
            '選択項目を指定する。
            .Column = Idx1
       'ツールチップテキストの表示
            .ToolTipText = value & " mm "
        Else
            .ToolTipText = ""
        End If
    End With
    
End Sub


●MSChartの色づけ
MSChartは個々のデータポイントに個別に色を指定することはできない PictureBoxを貼り付けて対処するべし。


●MSFlexGridでの複数選択
グリッドは標準ではCtrl,Shiftボタンを使って選択することができない。
http://funnystep.sakura.ne.jp/Wiki/tipsData/GridShift.txt
こんな感じで自作すればCtrl,Shiftによって複数選択が可能。

●FlexGridの固定行について

FixedRows = 1 Rows = 1にしたい時の話。
しかし、Rowsの値は、FixedRowsの値より最低1より大きな値を指定しなければいけないらしく、エラーが発生する。
そんな時は、

 Rows = 15 //ダミー
 FixedRows = 1
 Rows = 1 

のようにダミーを置くとうまく動作する。

●テキストボックスに数字しか入力できないように設定する。
SetWindowLong Text1.hwnd, GWL_STYLE, GetWindowLong(Text1.hwnd, GWL_STYLE) Or ES_NUMBER

●MsFlexGridに登録できるデータの個数。
登録できるデータは35万セルまで。
MsHFlexGridではそのような制限がないので、こちらを使うことを推奨。
若干デザイン違うが、色設定することでほぼ同じになる。


VC6.0

●VC6.0でボタンの色を変更したい時は、サブクラス化の必要がある。

クリップボードから文字列を取得する。

'クリップボードから文字列を取得してstrText、tempに保存する処理。
'(m_staticvalはCstring型のコントロールのパラメタ)
void CNICCALC_SIMPLEDlg::OnEditPaste?() 
{
	// TODO: この位置にコマンド ハンドラ用のコードを追加してください	
	CString strText;
	strText.Empty();

	// クリップボードにテキストデータが入っているかを調べる
	if( !::IsClipboardFormatAvailable?(CF_TEXT) )
		return ;
	// クリップボードのオープン
	if( !::OpenClipboard?(NULL) )
		return ;

	// クリップボードからデータを取得し、strTextへコピー
	HANDLE hMem = ::GetClipboardData?(CF_TEXT);
	LPTSTR pMem = (LPTSTR)::GlobalLock?(hMem);
	::lstrcpy((LPTSTR)(LPCTSTR)strText, pMem);
	::GlobalUnlock?(hMem);
	::CloseClipboard?();

	
	//strText = FuncPunctuation?(strText, FLIPFLOP_DOT);
   
	CString temp = strText;
	m_staticval = temp;

	UpdateData?(false);	
	return ;

}


クリップボードに文字列を貼り付ける

'文字列tempStrをクリップボードに貼り付ける時の処理。
'(m_staticvalはCstring型のコントロールのパラメタ)
void CNICCALC_SIMPLEDlg::OnEditCopy?() 
{
	
	CString tempStr;
	UpdateData?(true);
	tempStr = m_staticval;
	
	// 文字列が空の場合はコピーしない
	if( tempStr.IsEmpty?() ){
		AfxMessageBox?("str Empty\n");
		return ;
	}

	// クリップボードのオープン
	if( !::OpenClipboard?(NULL) ){
		AfxMessageBox?("Clipboard not Open\n");
		return ;
	}
	// ヒープ上にメモリ領域を確保し、文字列をコピー
	int iStrLen = tempStr.GetLength?() + 1;
	HGLOBAL hMem = ::GlobalAlloc?(GMEM_FIXED, iStrLen);
	LPTSTR pMem = (LPTSTR)hMem;
	::lstrcpy(pMem, (LPCTSTR)tempStr);

	// クリップボードへ文字列をコピーし、クローズ
	::EmptyClipboard?();	// クリップボードの中身を空にする
	::SetClipboardData?(CF_TEXT, hMem);
	::CloseClipboard?();
}

●OKボタン、ESCボタンへの対応

PreTranslateMessage(MSG* pMsg)を使うことで、メッセージを取得して
else if( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {}
else if( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE){}

と、上記のような感じでEnterキー、ESCキーを押した時の処理を上書きする。 こうしないと、enter,ESCを押した時にアプリケーションが終了する。