SWS
[ 上へ ] [ Visual C++ MDB その1 ] [ Visual C++ MDB その2 ] [ 本当の雑記帳 ]

本当の雑記帳


FAQもの(その1)
・起動時にドラッグ&ドロップされたファイル名を取得する方法
InitInstance内のcmdInfoを調べます。

if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen) {
    sFilename = cmdInfo.m_strFileName;
}

・関連付けされたアプリケーションでファイルを開きたいとき
ShellExecuteExを使用します。

sei.cbSize = sizeof(SHELLEXECUTEINFO);         //構造体サイズ
sei.fMask = SEE_MASK_FLAG_DDEWAIT;        //実行パラメータ
sei.hwnd = NULL;                 //エラー表示用ハンドル
sei.lpVerb = "open";                 //動作文字列
sei.lpFile = "filename.csv";    //実行対象ファイル名
sei.lpParameters = NULL;             //実行時パラメータ
sei.lpDirectory = NULL;             //作業ディレクトリ
sei.nShow = SW_SHOWNORMAL;                     //表示状態フラグ
ShellExecuteEx( &sei );                 //ファイル実行関数を実行

偉大な関数を発見
LCMapStringです。半角<->全角、小文字<->大文字、カタカナ<->ひらがなを行ってくれます。
引数はこんな感じ。

LCMapString(
LCID Locale, // ロケール識別子
DWORD dwMapFlags, // マップ変換の種類
LPCTSTR lpSrcStr, // マップ元文字列のアドレス
int cchSrc, // マップ元文字列の文字数
LPTSTR lpDestStr, // マップ先バッファのアドレス
int cchDest // マップ先バッファのサイズ
);

Localeには、
    GetSystemDefaultLCID()
dwMapFlagsには、
    LCMAP_FULLWIDTH(全角文字にします)
    LCMAP_HALFWIDTH(半角文字にします)
    LCMAP_HIRAGANA(ひらがなにします)
    LCMAP_KATAKANA(カタカナにします)
をいれます。他は解るよね。

char sDestStr[256];
    LCMapString(GetSystemDefaultLCID(),LCMAP_HALFWIDTH,"半角カナじゃガ−ん",-1,sDestStr,256);

おお!!、ちゃんと変換されるよ(涙)。

EXCELとCSVとか・・・
自分で作成したでCSVファイルを作成し、それをEXCELで読み込ませようとすることはよくあると思う。そんなときに困るのがEXCELの自動変換ですよね。どんなときはCSVを作成するときに=""で括っちゃうのが手っ取り早い方法です。
="TEST",="00002",="1/22",="1999/10/01"
こんな感じにね。

EXEがどんなDLLを呼び出しているか知りたい
VC++6.0に付属のDependency Walkerを使いましょう。大変便利です。こんな感じ↓。持っていない方はクイックビューアで ImportTableを見るしかないね。

DependencyWalker.jpg (116061 バイト)

フォント設定ダイアログのサンプル
FontDialogを使って簡単に実現します。下記の例は選択したフォント名を表示するものです。

LOGFONT log_font;

log_font.lfHeight = -15;
log_font.lfWidth = 0;
log_font.lfEscapement = 0;
log_font.lfOrientation = 0;
log_font.lfWeight = 400;
log_font.lfItalic = FALSE;
log_font.lfUnderline = FALSE;
log_font.lfStrikeOut = FALSE;
log_font.lfCharSet = 128;
log_font.lfOutPrecision = 3;
log_font.lfClipPrecision = 2;
log_font.lfQuality = 1;
log_font.lfPitchAndFamily = 17;
CFontDialog fDlg( &log_font, CF_EFFECTS | CF_SCREENFONTS );
fDlg.m_cf.lpLogFont = &log_font;
fDlg.DoModal();
    AfxMessageBox(log_font.lfFaceName);

ListCtrlの一行全体選択
今時のPCはIE4以上入っていると思いますので、拡張スタイルLVS_EX_FULLROWSELECTを使いましょう。。。ダメ?IE4が入っていませんね。だったらオーナードローでがんばれ!!

CString的トークン分割処理Part2
くそコーディングをした時って、人に見せたくなりませんか?私はとってもなります(笑)。で、本日誕生したくそコードがこれ↓。全角含みの文字列を20Byte単位で区切っています。でも、このままだと全角文字がそのまま分断されてしまうので、後ろの配列から強引に引っ張り込んでくる。つまり最長21Byteで分けているのね(笑)。インチキだーと思ったら、後ろの配列にくっつけれよう変更すれば良いだけ。くそコードに変わりはありません(爆)。

CStringArray sZenstrArray;
    sZenstrArray.SetSize(3);
    int nZenstrLen;
    sZenstrArray[0] = sZenstr.Mid(0,20);
    sZenstrArray[1] = sZenstr.Mid(20,20);
    sZenstrArray[2] = sZenstr.Mid(40,20);

    for(int i=0;i<(sZenstrArray.GetSize()-1);i++){
        nZenstrLen = sZenstrArray[i].GetLength();
        if(nZenstrLen == 0) continue;
        if(IsDBCSLeadByte(sZenstrArray[i][nZenstrLen-1])!=0){
            // 2バイト文字の先頭
            sZenstrArray[i]+=sZenstrArray[i+1][0];
            sZenstrArray[i+1].Delete(0);
        }
    }

CString的トークン分割処理
トークンの分割というか、ただCString内データのカンマ区切りをおこなう例を書いてみました。strData内のテキストをカンマ毎にarrayResultへ保存しています。ソースを見ていただけると解ると思うのですが、CStringのコピーコンストラクタが散乱していますのでスピードはかなり遅いです。翼君と岬君が合体して決めたときよりもさらに強力なオーバーヘッドがかかっているはず、っていうかこのネタの為に書いてみたんだけど・・・イマイチだな〜。SJIS対応はしていないので、漢字2バイト目に当てはまるような文字をcSepに使うと全く機能しないでしょう。まともに組もうという志がある方はここの「strtok、2バイト文字について」を正座して読み、自分でCString仕様に作り替えてみて下さい。そして良いのが出来たら私にください。お・ね・が・い・ね♪。

CString strData = "分けたい,分ければ,分けようとも,分かれたくない,お願い許して,俺が悪かった";
CStringArray arrayResult;
char cSep=',';
int nPos;

    while(1){
        nPos = strData.Find(cSep);
        if(nPos==-1){
            arrayResult.Add(strData);
            break;
        }
        else{
            arrayResult.Add(strData.Left(nPos));
        }
        strData = strData.Mid(nPos+1);
    }
    int size = arrayResult.GetSize();
    for(int i=0;i<size;i++){
        AfxMessageBox(arrayResult[i]);
    }

ptrdiff_tって知っています?ポインタの差値用に使うらしい。知らなかったぞ。えっへん。

昔掲示板で出てきたネタがあるのですが、もったいないのでまとめてみようと思う。

VB(5)にてTXTをデータベースとして扱う方法(ODBC)???

@ オラクル、SQLサーバーなどのネットワーク系DBのDBアクセスを、
  ODBCダイレクトという方式でやる。
A オラクルなどで制御しにくい場合、ACCESSにODBC経由で
  DBをリンクして、データ制御を行う。

CSV形式のファイルを、DBとして使うなら、
1、データコントロールをフォームに張り付け。
2、データコントロールのプロパティに以下を設定
  connect=text;
DatabaseName=[ファイルのフルパス]
  Recordsource=テキストファイル名
そんで実行。

3、ファイルの1行目が、フィールド名称として、格納されます

  例)c:\tade\Temp\a.txt
  
    TXTファイルの中身:
  "a","b","c"
  1,2,3
  4,5,6

サンプルプログラム)
  Private Sub Form_Load()

   Data1.Connect = "text;"
   Data1.DatabaseName = "C:\tade\TEMP"
   Data1.RecordSource = "a#txt"

   Data1.Refresh

    With Data1.Recordset
   .MoveFirst
   Do Until .EOF
  Call MsgBox(.Fields("a").Value & " " & _
.Fields("b").Value & " " & _
.Fields("c").Value)
  .MoveNext
   Loop
  End With

   MsgBox ("おわり")

   End

  End Sub

  メッセージボックスにテキストの内容を出すだけです。
  こんな感じで、TXTをDBもどきとして使用することもできます。


今日はC++の仮想関数についてまとめてみることにします。うんちくは気が向いたときにささっと書く予定です。
注)仮想関数を持つクラスを定義するときは,そのクラスのデストラクタの宣言にもvirtualをつける必要があります。

// CVVVTotalPrint (派生 Class1)
class CVVVTotalPrint : public CTotalPrint
{
public:
    ・・・・・・・・・・・・
    virtual void DataOut(void){ AfxMessageBox("DataOut"); }
};

// CSSSTotalPrint (派生 Class2)
class CSSSTotalPrint : public CTotalPrint
{
public:
    ・・・・・・・・・・・・
    virtual void DataOut(void){ Beep(n); }
};

//------------------------------------------------------------------
// CTotalPrint (Base Class)
class CTotalPrint
{
public:
    ・・・・・・・・・・・・
    virtual void DataOut(void)=0;
};

//------------------------------------------------------------------

CVVVTotalPrint total_print1;
    total_print1.DataOut();        // メッセージボックスが表示される

CSSSTotalPrint total_print2;
    total_print2.DataOut();        // Beepが鳴る

CStringクラスを使うと手抜きが出来てなかなか便利です。
例:拡張子を取り出す

CString sHead,sTail;
int pos = sFilename.ReverseFind('.');
if(pos!=-1){
    sHead = sFilename.Mid(0,pos);
    sTail = sFilename.Mid(pos+1);
}

たまたまVC6でスタックのサイズを変える必要がありました。設定する場所は、「プロジェクト」->「設定」メニューの「リンク」タブでカテゴリのリスト選択からアウトプットを選びます。スタックアロケーションというeditで設定可能です。defaultは1MBだそうです。
#コールバックの再起呼び出しには注意しましょう。すぐにスタックが溢れます。ほら、あなたのプログラムにも魔の手がっ(自爆)。

「勝手に変なメッセージだすんじゃね〜」のコーナー
ドキュメント作成時にメモリ不足で失敗すると「空のドキュメントが作成できません」という意味不明のメッセージが出ます。なんのこっちゃ?要はメモリ不足でコケているのですが、あまりに解りにくい。。。(というかこの文章自体が解りにくい(爆死))。というわけでメッセージ変更しちゃいましょう。環境はVC5+MFCです。

メニューの [表示] - [インクルードファイルの設定]で設定ダイアログを開き、
#define _AFX_NO_FILECMD_RESOURCES
を追加します。変更を有効にするために一度プロジェクトを閉じてもう一度開けば、AFX_IDP_FAILED_TO_CREATE_DOC を自分のアプリ内のリソースで作成することが出来ます。
ただし、これをおこなうと、
AFX_IDP_INVALID_FILENAME
AFX_IDP_FAILED_TO_OPEN_DOC
AFX_IDP_FAILED_TO_SAVE_DOC
AFX_IDP_ASK_TO_SAVE
AFX_IDP_FILE_TOO_LARGE
AFX_IDP_FAILED_TO_START_PRINT
なんかを追加しないといけないかもね♪