Programing Guide

複数のサーバーに分割しています。
直接リンク出来ないときはトップページからたどって下さい。
前田稔(Maeda Minoru)の超初心者のプログラム入門

Programing Guide Index

文字コードの説明

    Shift_JIS & Unicode

  1. Windows の文字コードには Shift_JIS(ANSI) 文字セットと Unicode 文字セットがあります。
    昔は必ず Shift_JIS を使ったものですが、最近のコンパイラでは Unicode が主流になってきました。
    Unicode にも 8 bit, 16 bit, 32 bit, etc が存在します。
    Shift_JIS では、英数字や一部の記号を8ビットで、ひらかなや漢字などを16ビットで表現します。
    8bit Unicode も MultiByte(8 Bit or 16 Bit Charcter Set) に含まれると思うのですが、一般的に MultiByte と言えば Shift_JIS を指すようです。
    普通 Unicode と言えば utf-16 を指すようですが、ソースプログラムファイルには utf-8 が使われています。
  2. Unicode には BOM が格納されているものと、格納されていないものがあります。
    BOM(byte order mark)とはテキストファイルの先頭に格納される文字コードを示すIDです。
    文字コード BOM 説明
    utf-16 FFFE 先頭2バイトが BOM です
    utf-8 EFBBBF先頭3バイトが BOM です
    utf-8(BOM無し) BOM は格納されていません
    BOM が格納されていると Encoding で間違った設定をしても、文字化けすることなく正しく読むことができます。
    最近ではソースプログラムや HTML ファイルに utf-8 が良く使われるようになってきました。
    Shift_JIS(ANSI), Unicode 以外にも文字コードは山のように存在します。
    詳しい説明は Encoding クラス を参照して下さい。
  3. プログラムの内部コードとしては Shift_JIS と 16 bit Unicode が使われています。
  4. C# では文字データを定義する char 自体がワイドキャラ(16 bit Unicode)になっています。
    Windows8 以降(ストアアプリ)の C++ では Unicode が標準で String^ も Unicode になっています。
    Windows7 までの C++ では、UnManeged Mode が Shift_JIS で Maneged Mode が Unicode です。
    また STL の string は Shift_JIS になっているので、注意が必要です。
    STL で Unicode を使うときは wstring を使います。
  5. マルチバイトから Unicode に変換するときは MultiByteToWideChar() 関数を使うのが簡単です。
    sjis, -1, でマルチバイトの領域を指定します。
    -1 を指定すると、文字列の終わりを示す NULL までが文字列長になります。
    変換に失敗するとゼロが、成功するとバッファに書き込まれたワイド文字の数が返ります。
    LPSTR   sjis = "Shift JIS code";
    WCHAR   buf[MAX_PATH];
    
    MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,sjis,-1,buf,MAX_PATH);
    
    Unicode から マルチバイトに変換するときは WideCharToMultiByte() 関数を使います。
    uni, -1 でワイドキャラクタの領域を指定します。
    -1 を指定すると、文字列の終わりを示す NULL までが文字列長になります。
    buf, MAX_PATH で受け取り側の領域を指定します。
    変換に失敗するとゼロが、成功するとバッファに書き込まれたバイト数が返ります。
    LPWSTR  uni = L"uni code String";
    LPSTR   sjis = "Shift JIS code";
    char    buf[MAX_PATH];
    
    WideCharToMultiByte(CP_ACP,0,uni,-1,buf,MAX_PATH,NULL,NULL);
    
  6. C# の入出力メソッドは、多種多様な文字コードに対応しています。
    詳細は C# File 入出力 を参照して下さい。

ストリング関係のページを抜粋

  1. 文字列(char の配列)で最も悩まされるのは、文字列の長さの問題です。
    必要以上に大きな領域を確保するのも気が引けますし、領域をオーバーしてアクセスすると何が起こるか解りません。
    特にサイズが確定しないメモリ領域をダイナミックにアロケートするときには、何時も悩まされます。
    この問題を一挙に解決してくれるのが String(string) です。
    ストリングは STL や C++ Maneged や Windows8(10) や C# や MFC で独自のストリング機能がサポートされていて、それぞれ書き方や機能が異なるのが混乱の原因です。
    デバッグ情報の印字は 出力ウインドウに書き出す を参照して下さい。
  2. C# に備わっているマネージドの string です。
    マネージドモードでは C++ Maneged と互換性があり、同じ機能が使えるはずです。
    C# の string はわりと充実していて、わざわざ STL を使う必要は無いでしょう。
    string
    曜日と経過日数
  3. 機能が充実していて、使いやすいのは STL の stirng です。
    私は C++ UnManeged やストアアプリ(Windows10 など)で利用しています。
    STL のプログラムは using namespace で std で宣言されたネームを使えるようにします。
    using namespace std;
    
    string の基礎
    Win8 STL string
    Win8 STL Vector
    Win10 OBJ Model
    Win10 NormModel
  4. C/C++ の String は幾つかのタイプに分かれます。
  5. MFC の CString Class も使う事が出来ますが、ちょとわかりにくいかな?
    MFC CString Class
  6. Windows8 の string は機能が低くて役に立ちません。
    Win8 String
    Week Class
  7. RichTextBox(RichEdit)を使うと string 関係のメソッドが実装されています。
    TextBox も RichTextBox に準じます。(よく似た使い方が出来るのですが、違いもあります。)
    C# RichTextBox
    Windows RichEdit の基礎
開発環境
  1. 最近の開発環境は複雑怪奇です。
    Shift-JIS と Unicode だけでもややこしいのに Maneged Mode やらセキュリティの強化やら止めはストアアプリ(Windows10)です。
    特にC言語の開発環境には注意して下さい。
    開発環境が異なると説明どおりには動きません。
    私のページもそうでしょうが、ネットから検索したページも様々な開発環境が混在していて何が何やらわからない場合があります。
  2. vista からシステムの安定とセキュリティの強化から (^_^;) 不正(不用意)なメモリ領域へのアクセスを厳しく管理するようになりました。
    今まで問題なく通っていた string 関係の関数を中心として warning(警告)が発せられます。
    また CPU も16ビット→32ビット→64ビットの移行に伴い、古いプログラムが動かなくなっています。
    16ビットモードで作成されているプログラムやライブラリやDLLは使えないようで、32ビット(64ビット)で再コンパイルして下さい。
  3. warning(警告)が発せられる文字列関係の関数と対処の方法です。
    文字列処理は先に説明したストリング(String, string)で処理するのがベストです。
    今まで文字列操作は strcpy や lstrcpy 等を使っていましたが、これらはいとも簡単に確保したバッファ以上の領域に文字列を書き込んでしまいます。
    そこでオーバーランをしないよう考慮した関数が strsafe.h で提供されています。
    詳細は <strsafe.h> で追加された文字列操作関数について を参照して下さい。

Program Debug Note

    デバッグガイド

  1. Debug Tool に依存しすぎると、無駄な時間ばかり浪費してろくなことはありません。
    デバッグに必要な情報を表示するソースコードをプログラムに組み込みましょう。
    ①MessageBox などを利用する。
    ②WriteLine などで出力ウインドウに書き出す。
    ③this.Text などでウインドウのキャプションに常時表示する。

    MessageBox を使う

  2. MessageBox() はどこからでも手軽に利用することが出来るので、デバッグのときに重宝します。
    C++ の MessageBox です。
    WindowsC のページから MessageBox を表示するプログラムの終了を確認する などを参考にして下さい。
    MessageBox(NULL,"Message Box を表示","Message Box Test",MB_OK);
    
    応答確認でプログラムを中断します。
    int     id;
    id = MessageBox(NULL,(LPCSTR)"終了しますか",
           (LPCSTR)"終了確認", MB_OKCANCEL | MB_ICONQUESTION);
    if (id==IDOK)  DestroyWindow(hWnd);
    
    DMsg() 関数を定義してみました。
    #include    <strsafe.h>
    void    DMsg(char *msg, int n)
    {   char    str[80];
        StringCbPrintf(str,80,"%s[%d]\n",msg,n);
        MessageBox(NULL,str,"Debug Message",MB_OK);
    }
    
    Unicode の場合です。
    #include    <strsafe.h>
    void    DMsg(WCHAR *msg, int n)
    {   WCHAR  str[80];
        StringCchPrintf(str,80,L"%s[%d]\n",msg,n);
        MessageBox(NULL,str,L"Debug Message",MB_OK);
    }
    
  3. C++ Maneged モード の書き方です。
    C++のページから MessageBox を表示する などを参考にして下さい。
    MessageBox::Show("プログラムを終了します","Message Box");  
    
  4. C# の MessageBox の書き方です。
    C#のページから マウスのクリックを検出するマウスのクリックで終了確認 などを参考にして下さい。
    MessageBox.Show("プログラムを終了します","Message Box");
    MessageBox.Show("Mouse がクリックされました");
    
    応答確認でプログラムを中断します。
      DialogResult rc;
      rc= MessageBox.Show("終了しますか","選択",
          MessageBoxButtons.YesNo,MessageBoxIcon.Question);
      if (rc == DialogResult.Yes) Application.Exit();
    
  5. ストアアプリでは MessageDialog を使います。
    Windows8 C++ の書き方です。
    Windows::UI::Popups::MessageDialog^ dlg =
        ref new Windows::UI::Popups::MessageDialog("Test Message");
    dlg->ShowAsync();
    
  6. Windows8 C# の書き方です。
    Windows.UI.Popups.MessageDialog dlg =
        new Windows.UI.Popups.MessageDialog("Message Dialog");
    dlg.ShowAsync();
    

    出力ウインドウに書き出す

    応答するのが面倒なら Visual Studio の出力ウインドウを使う 方法がお勧めです。
    Unicode が主流になって来たので、Unicode で印字する方法を説明します。
  7. OutputDebugString() のメッセージは、Debug モードで実行した時に出力ウインドウに表示されます。
    Debug モードで実行が終わった後で「出力」タブをクリックして下さい。
    普通に実行した場合は全く影響が無く、デバッグ情報の収集に適しています。
    OutputDebugString() は、Windows10/C++ でも Windows10/DirectX でも使用可能です。
    受け取るパラメータ(文字列)は LPCWSTR として定義されています。
    #include <windows.h>    //OutputDebugString
        OutputDebugString(L"Test Debug Message\r\n");
    
    C++ Maneged Mode では WriteLine を使う方法がお勧めです。
    C++のページから Debug 関数を定義 などを参考にして下さい。
    using namespace System;
    
        Console::WriteLine("val={0} str={1}", val,str); 
    
    Shift-JIS のときは WCHAR に変換して印字します。
        void XLoader::Debug(char *str)
        {
            WCHAR   wk[1000];
            MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,str,-1,wk,1000);
            OutputDebugString(wk);
            OutputDebugString(L"\r\n");
        }
    
    String^ で OutputDebugString を使うときは、PtrToStringChars() で wchar_t のポインタを取得します。
    #include <windows.h>
    #include <vcclr.h>
    using namespace System;
    
    void Debug(String^ msg)
    {
        String^ message = msg + "\r\n";
        pin_ptr<const wchar_t> wch = PtrToStringChars(message);
        OutputDebugString(wch);
    }
    
  8. ストアアプリの String^ の基本的な使い方です。
    C++ Maneged Mode の String^ とは仕様が異なるようです。
    Maneged Mode でコンパイルすると msg->Data() がエラーになります。
      Platform::String^ msg = L"String Message\n";
      OutputDebugString(msg->Data());
    
    String^ を引数に持つ Debug() 関数を定義してみました。
    using namespace Platform;
    
    void Debug(String^ msg)
    {   String^ str = "Message[" + msg + "]\n";
        OutputDebugString(str->Data());
    }
    
    String^ と int を引数に持つ場合です。
    void Debug(String^ msg, int n)
    {
        String^ message = ref new String(msg->Data());
        message += "  ";
        message += n.ToString();
        message += "\r\n";
        OutputDebugString(message->Data());
    }
    
  9. ref class(ref new で生成) と従来の class(new で生成) とでは少し仕様が異なるので要注意です。
    ref class MainPage の場合です。
    swprintf() を使って文字列編集するのが便利なようです。
    MainPage::MainPage()
    {
        InitializeComponent();
        OutputDebugString(L"★Debug Test\r\n");
        Debug(L"Call Degug", 123);
        int t[] = { 1, 4, 3, 5, 2 };
        Debug(t, 5);
    }
    void MainPage::Debug(LPWSTR msg, int val)
    {
        wchar_t str[80];
        swprintf(str, 80, L"%s: %d\r\n", msg, val);
        OutputDebugString(str);
    }
    void MainPage::Debug(int *t, int num)
    {
        Platform::String^ str;
        for (int i=0; i<num; i++)
        {   str = t[i].ToString();
            str += "\r\n";
            OutputDebugString(str->Data());
        }
    }
    
    MainPage.xaml.h の関数宣言です。
    namespace App1
    {   public ref class MainPage sealed
        {
        public:
            MainPage();
            void Debug(LPWSTR msg, int val);
            void Debug(int *t, int num);
        };
    }
    
  10. ストアアプリの C# では Debug.Write(); を使います。
    C# WPF では Console.WriteLine() も使えるようですが、OutputDebugString() は使えません。
    Debug.Write() を使うときは using System.Diagnostics; を定義して下さい。
    Debug モードで実行が終わった後で「出力」タブをクリックして下さい。
    using System.Diagnostics;
        Debug.Write("\n*** Debug Message ***\n");
    
  11. Unity Game Engine では Debug.Log(); が使われます。
    JavaScript や C# のスクリプトを使うのですが、どちらも同じです。
        Vector2 pnt = Input.mousePosition;
        Debug.Log("x->" + pnt.x + "  y->" + pnt.y);
    
  12. C#(XNA)では Console.WriteLine() を使う方法がお勧めです。
    Debug モードで実行が終わった後で「出力」タブをクリックして下さい。
    キー操作で幅と高さを変更する などを参考にして下さい。
    Console.WriteLine("val={0} str={1}", val,str); 
    
  13. Javaでは System.out.println() を使う方法がお勧めです。
    System.out.println("a の値: " + a); 
    
  14. Visual Studio で「Unicode 文字セットを使用する」に設定して STL の string(wstring) を使用する場合です。
    string は Shift-JIS なので Unicode に変換して印字します。
    STL のプログラムは using namespace で std で宣言されたネームを使えるようにします。
    #include <windows.h>    //OutputDebugString
    #include <string>
    using namespace std;
    
        void Debug(string msg)
        {   WCHAR   wk[1000];
            MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,msg.data(),-1,wk,1000);
            OutputDebugString(wk);
            OutputDebugString(L"\r\n");
        }
    
    wstring は Unicode なので msg.data() で印字します。
    void Debug(wstring msg)
    {   OutputDebugString(msg.data());
    }
    

    タイトルバーに表示する

  15. 常に確認したい重要な情報は、ウインドの Title Bar を使って表示する方法がお勧めです。
    C++ Maneged Mode で Mouse Down をカウントして Title Bar に表示してみます。
    Mouse Count などを参考にして下さい。
        virtual void OnMouseDown(MouseEventArgs^ e) override
        {   cnt++;
            this->Text = "cnt=" + cnt;
        }
    
    C++ Maneged Mode で VerMsg() 関数を作成してみました。
    キー操作で画像を移動する などを参考にして下さい。
        void VarMsg(String^ msg, int x, int y)
        {   String^ message = msg + " " + x + " " + y;
            this->Text = message;
        }
    
    C#で Title Bar にデバッグ情報を表示する VarMsg() 関数です。
        // Title Var Message
        public void VerMsg(string str, int val)
        {   string wstr;
            wstr = str + val.ToString();
            this.Text = wstr;
        }
        //VarMsg() 関数の呼び出し方
        VerMsg("CNT= ", CNT);
    
    XNA(C#)で Title Bar に表示する方法です。
        base.Window.Title = "Title Bar に表示";
    
    STL を使って Title Bar にデバッグ情報を表示する VarMsg() 関数です。
        // Title Var Message
        public void VerMsg(string str, int iv, float fv)
        {   string wstr;
            wstr = str + "iv=" + iv.ToString() + "  fv=" + fv.ToString();
            base.Window.Title = wstr;
        }
        //VarMsg() 関数の呼び出し方
        VerMsg("int 型と float 型  ",ival,fval);
    
    Title Bar の表示は基本的には MessageBox や OutputDebugString で印字していた情報をウインドウのキャプションに設定するだけです。
    次のページなどを参考にして下さい。

    Script 言語

  16. Script 言語はコンパイルしないで、実行時にソースコードを解析しながら実行されます。
    HTML と組み合わせて使われる代表的な言語として JavaScript, PHP, Perl などがあります。
    HTML に組み込む前に、コマンドプロンプトを起動してエラーチェックが出来る場合もあり、事前にエラーをチェックして文法エラーなどを無くしておきましょう。
  17. Java Script では実行時にエラーが発見されると処理を中断します。
    最近ではブラウザにデバッグ機能が実装されていて、Internet Explorer11 では[F12]キーでこの機能を利用することが出来ます。
    デバッグ機能を起動すると処理が中断したときの場所や原因を教えてくれます。 (●^o^●)
    また console.log() でデバッグに必要な情報を書き出すことも出来ます。
    (console.log は Firefox や Google Chrome では F12 から Console TAB で表示されます)
    (Edge では [F12 から Console TAB] でデバッグウインドウを表示して実行すると log メッセージが表示されます)
    デバッグ機能に頼りすぎると、訳のわからない事も多くかえって混乱します。
    詳細は 開発に便利な JavaScript について などを参照して下さい。
    Java Script のデバッグで頼りになるのは document.write() と window.alert() でしょうか。
    document.write("実行を確認しました<br>"); はホームページ上に表示されます。
    window.alert("ここまで実行されました"); はダイアログボックスで知らせてくれます。
        var a = 3;
        var b = 5;
        document.write("a=", a, ": b=", b, "<br>");
        window.alert("a=" + a);
    
  18. PHP では print 関数や print_r 関数を使います。
    print_r では配列や連想配列を指定すると、全ての要素を印字してくれます。
    . は文字列の連結演算子です。
        print "Hello PHP";
        print "<IMG SRC=\"img/jewel.gif\">\r\n";
        print("first:$first  :last:$last\r\n");
        print "'AB' not found" . "\r\n";
        print_r($ary);
    
    また var_dump を使うと現在の属性と値を印字してくれます。
    $a = 'hoge';
    var_dump($a);
    var_dump($ary);
    
  19. Perl では print 関数を使います。
    . は文字列の連結演算子です。
    $v1= 2;
    $v2= $v1+3;
    print "$v1,$2\n";
    print "v1=" . $v1 . "\n";
    
    配列名なども直接指定することが出来ます。
    @data= (3,1,4,5,2);
    print @data;
    

デバッグツール

  1. Visual Studio の Debug 機能を説明します。
    DebugSystem に依存しすぎると無駄な時間ばかり浪費してろくなことは無いのですが、 利用の仕方によっては大変有効なツールになります。
    Visual Studio でプログラムのデバッグを行う方法を説明します。
  2. Debug キー操作一覧です。
    動作 キー ツールマーク
    HELP F1 関数にポイントしておくと説明が表示される
    実行 Ctrl+F5 赤いビックリマーク
    ステップ F5 文章+↓
    ブレーク設定 F9 手のひら
    ブレーク解除 F9 手のひら
    Step 実行 F10
    カーソルまで実行Ctrl+F10
    Step In F11
    Step Out Shift+F11
    Debug 中止 Shift+F5
    MemoryWindow Alt+F6
    説明の画像
  3. Debug の方法です。
  4. エラーコードを調べる
    エラーコードで終了したときには、その数値が持っている意味を調べなければなりません。
    Visual Studio 付属の VC++ エラールックアップツールを使うと簡単にエラー値からエラー内容がわかります。
    環境や Visual Studio のバージョンによって異なりますが、例えば私の環境では [スタート][全てのプログラム][Visual Studio .NET][Visual Studio .NET ツール][Visual C++エラールックアップ]でエラー検索ツールを実行します。
    ただし、メッセージの説明は余りにも不親切で、あまりデバッグの役には立つとは思えません。

  5. 関数や構造体やキーワードの定義を調べる方法です。
    USHORT を調べる場合を例にして説明します。
    キーワードの位置にマウスを置いて右クリックします。
    「USHORT の定義位置を表示」を選択します。
    説明の画像
    ビルドを確認する DialogBox が表示されます。
    「はい」をクリックするとビルドが実行されます。
    説明の画像
    キーワードが定義されているファイル名とその定義が表示されます。
    説明の画像
  6. デバッグ操作の補足

Error Guide

初心者にとって、なれない言語のエラーほど厄介なものはありません。
プログラムを作成する上で、分かり難いエラーと対策を抜粋します。
一般的な文法エラーなどは、対象としていないので念のため。 (^_^;)

    コンパイル時のエラー

  1. 次のエラーが表示される。
    C:\DATA\C#\BAT\Prog1>csc Hello.cs
    'csc' は、内部コマンドまたは外部コマンド、
    操作可能なプログラムまたはバッチ ファイルとして認識されていません。
    
    C#のコンパイラ(csc.exe)に対して、パスが通っていません。
    次のページを参照して、パスと環境変数を設定して下さい。
    CLIで操作 または Command Line から Windows プログラムを実行 などを参考にして下さい。
  2. 次のエラーが表示される。
    hello.cpp(5) : fatal error C1190: マネージ ターゲット コードには '/clr' が必要です。
    
    マネージモードのプログラムをコンパイルするときは、次のようにタイプします。
    cl /clr hello.cpp
    ネイティブモードの場合は、次のようにタイプします。
    cl gcm.cpp
    ネイティブモードに /clr を付けてもコンパイル出来ますが、Maneged Code が生成されます。
    cl /clr gcm.cpp
    直接コマンドを叩くときは CLIで操作 を参照してパスと環境変数を設定して下さい。
  3. 次のエラーが表示される。
    Gcm.cs(14,19): error CS0120: 静的でないフィールド、メソッド、またはプロパティ
        'console.gcm(int, int)' で、オブジェクト参照が必要です。
    
    Static 関数はインスタンス化しなくても呼び出すことが出来る関数です。
    Main() は Static で宣言しなければなりません。
    また Static 関数から参照する関数やデータは Static で宣言する必要があります。
    今回は gcm() メソッドを static で宣言するとエラーが消えました。
    メソッド(method) の定義 などを参考にして下さい。
  4. 次のエラーが表示される。
    グローバルまたは静的変数は、マネージ型 「・・・」 を含むことはできません
    ref クラス または値型の内部で、スタティック データ メンバのみ初期化することができます
    グローバル領域でマネージ型の初期値の設定は出来ません。
    static int main() {・・・} の中、または static で宣言して下さい。
    class 定義の中で、文字列変数を static で宣言して、初期値を設定してみました。
    static String^ wt = "日月火水木金土";
    誕生日の曜日 などを参考にして下さい。
  5. 次のエラーが表示される。
    エラー 1  型または名前空間名 'ArrayList' が見つかりませんでした。
    using ディレクティブまたはアセンブリ参照が不足しています。
    C:\DATA\C#\02Console\15ArrayList\01ListInt\Prog.cs 11 9 Prog
    
    using ディレクティブが不足しているときや、DLL の追加が必要なときに表示されます。
    今回は using System.Collections; を追加するとエラーが消えました。
    ArrayList の基礎 などを参考にして下さい。
  6. 次のエラーが表示される。
    Recycle.cs(8,29): error CS0234: 型または名前空間名 'FileIO' は名前空間 'Microsoft.VisualBasic' に存在しません。
    アセンブリ参照が不足しています。
    
    ゴミ箱を使うときは Microsoft.VisualBasic.dll を組み込みます。
    コマンドプロンプトからコンパイルするときは、次のようにタイプして下さい。
    csc /r:Microsoft.VisualBasic.dll Recycle.cs
    Folder Delete などを参考にして下さい。
  7. 次のエラーが表示される。
    エラー 1  型または名前空間名 'Drawing' は名前空間 'System' に存在しません。
    アセンブリ参照が不足しています。
    C:\DATA\C#\01テンプレート\03MyForm\Test\Console.cs 5  14 Console
    
    エラー 2  型または名前空間名 'Windows' は名前空間 'System' に存在しません。
    アセンブリ参照が不足しています。
    C:\DATA\C#\01テンプレート\03MyForm\Test\Console.cs 6  14 Console
    
    エラー 3  型または名前空間名 'Form' が見つかりませんでした。
    using ディレクティブまたはアセンブリ参照が不足しています。
    C:\DATA\C#\01テンプレート\03MyForm\Test\Console.cs 9  23 Console
    
    using ディレクティブが不足しているときや、DLL の追加が必要なときに表示されます。
    今回は Windows のプログラム(CSForm.cs)を DLL を取り込まずに実行してみました。
    Form を作成する などを参考にして下さい。
  8. 次のエラーが表示される。
    'C:\DATA\C#\DLL\Hello.dll' への参照を追加できませんでした。
    ファイルにアクセスできて、有効なアセンブリであること、または COM コンポーネントであることを確認してください。
    
    Win32 で作成した DLL を、そのまま C# のプロジェクトに格納することは出来ません。
    CS⇒Win32DLL などを参考にして下さい。
  9. 次のエラーが表示される。
    エラー  1  インスタンス参照で静的メンバ 'Wrapper.Wrap.func()' にアクセスできません。
    typename を代わりに使用してください。
    C:\DATA\C#\10DLL\CS_CLI\01Hello\Console.cs 12  9  Console
    
    static 宣言が原因で、static を外すと OK でした。
    static void func(); → void func();
    CS⇒Win32DLL などを参考にして下さい。
  10. 次のエラーが表示される。
    エラー  1 fatal error C1107: アセンブリ 'Microsoft.DirectX.dll' がみつかりませんでした:
    /AI または LIBPATH 環境変数を使用してアセンブリ検索パスを指定してください。
    
    プロジェクト・プロパティから[構成プロパティ][C/C++][全般]を選び、[#using参照の解決] にライブラリのパスを指定します。
  11. VC/C++ の警告について特定のコード分析を有効または無効にする方法です。
    有効にするときは enable を、無効にするときは disable を、規定値に戻すときは default を設定します。
    4995(文字列関係)の警告を無効にします。
    4995 などは警告が表示されたときに付けられている番号です。
    #pragma warning(disable: 4995)
    
    STL などで名前が長すぎる警告を無効にします。
    4786 4788 などは警告が表示されたときに付けられている番号です。
    #pragma warning(disable:4786 4788)
    
    現在のワーニングの抑制を変更したい場合には、以下のようにすると便利です。
    #pragma warning(push)
    #pragma warning(disable: 4192)
    #pragma warning(disable: 4278)
    // ここでインクルード等のコードを記述します。
    #pragma warning( pop )
    

    リンク時のエラー

  12. リンク時のエラーは、主に使われている関数が見つからないときです。
    ヘッダーファイルの取り込み、.lib や .dll の組込に注意して下さい。
    呼び出している関数の名前や引数が一致しないときも、別の関数とみなされます。
  13. 次のエラーが表示される。
    /out:Test.exe
    Test.obj
    LINK : fatal error LNK1561: エントリー ポイントを定義しなければなりません。
    
    プログラムにエントリー ポイントが定義されていません。
    今回のケースでは int Main() になっていました。
    C# は Main() ですが C++/CLI は main() です。

    実行時のエラー

  14. 実行画面が表示されない。
    実際に画面が表示されない場合と、表示はされているが瞬間に消える場合があります。
  15. 次のメッセージが表示される。(try_1.exe は実行中のプログラム名)

    このエラーは、実行時に予期しないエラーが発生したときに表示されます。
    キャンセルすると、エラーの原因が表示されるので確認して下さい。
    エラーを処理する catch { } を記述すると表示されなくなります。
    今回は Int32.Parse(strNo); で strNo に数値に変換出来ない文字列が格納されていました。
    プログラム例は try&catch を参照して下さい。
  16. 次のメッセージが表示される。
    ThredStateException はハンドルされませんでした。
    OLE が呼び出される前に、現在のスレッドが Single Thread Apartment(STA)
    モードに設定されていなければなりません。
    Main() に Single Thread Apartment(STA)モードを設定します。
    プログラム例は 画像ファイルを選択 を参照して下さい。
  17. 次のメッセージが表示される。
    アプリケーションのコンポーネントで、ハンドルされていない例外が発生しました。
    上のメッセージに続いて、エラーの原因が表示されるので、確認して下さい。
    エラーが予想されるときは try { } 及び catch { } でエラーが発生したときの処理を記述します。
    今回は Main() に [STAThread] を設定するとOKでした。
  18. 次のメッセージが表示される。
    InvalidOperationException はハンドルされませんでした。
    この例外はデバッガがプロセスにアタッチされている場合にのみ発生します。
  19. 次のメッセージが表示される。
    ReadOnly.exe は動作を停止しました。
    
    ハンドルされていない例外: System.IO.FileNotFoundException:
    ファイル 'C:\TMP\work.txt' が見つかりませんでした。
    
    ReadOnly の設定/解除で 'C:\TMP\work.txt' が見つかりませんでした。
    テスト用のファイル(C:\TMP\work.txt)を格納するとOKでした。
    プログラム例は Folder Delete を参照して下さい。
  20. 次のメッセージが表示される。
    FileNotFoundException はハンドルされませんでした。
    ファイル 'C:\TMPコピー ~ Work.txt がみつかりませんでした。
    
    ファイル名 "C:\TMPコピー ~ Work.txt" が間違っていました。
    正しくは "C:\TMP\コピー ~ Work.txt" です。
  21. 次のメッセージが表示される。
    MSVCR80.dll がないため、プログラムを開始できません。
    
    実行形式のプログラムをコピー(移動)するときは manifest も一緒にコピーして下さい。
    プログラム例は Console Mode のプログラムを動かす を参照して下さい。
    このエラーは幾つかのケースで表示されますが MSVCR80.dll には直接関係しないようです。
    MSVCR80.dll を探し出して格納しても、また別の DLL で引っかかります。
    その DLL を探し出して格納しても、また別の DLL で引っかかります。
    最善の方法は、実行形式のプログラムを格納するフォルダで直接コンパイルすることのようです。
  22. 次のエラーが表示される。
    マネージ デバッグ アシスタント 'LoaderLock' では 'c:\data\cli\directx\11dxform\debug\DXForm.exe' に問題を検出しました。
    
    メニューの【デバッグ → 例外】から、Managed Debugging Assistants の LoaderLock の項目の[スローされるとき]のチェックを外します。
    プログラム例は DirectX のプロジェクトを構築する を参照して下さい。

    ストアアプリ Error Guide

  23. Windows ストアアプリの C++ が従来の .NET Framework のものではなく、新しい WinRT というAPIを利用しています。
    従って Windows7 以前の API とは何かと様子が違うようです。
    Windwos8 のエラーメッセージは特に不親切です。
    チェックが厳重になったこともあり、コーディングも大変です。
    左辺と右辺の属性が異なったり、関数の引数の属性が一致しないと、その行にエラーが表示されます。
    私の経験から、エラーが表示された行の原因調査は、次の手順で行う方法をお勧めします。
    1. Visual Studio 上でメソッド(関数)のタイプを始めると「候補の一覧」が表示されます。
      候補の一覧にメソッドの名前が表示されないときは、ヘッダファイルや using の設定が不足しています。
      または、そのメソッドはサポートされていません。
    2. 名前空間(using namespace)が異なる(設定されたいない)とエラーになるので、これも確認して下さい。
      例えば String は Platform の名前空間で定義されています。
      従って、using namespace Platform; を設定して下さい。
      using namespace Platform;
      
      String^ msg = ref new String(L"Windows8 String Message");
      
      namespace を設定しないで、次のように記述することも出来ます。
      Platform::String^ msg = ref new Platform::String(L"Windows8 String Message");
      
    3. メソッド名のタイプが終わると、パラメータの説明が表示されます。
      説明に従って、パラメータをタイプして下さい。
    4. 行のタイプを終えても、メソッド(行)のエラーが消えないことがあります。
      実はこのエラーが最も厄介で、左辺と右辺の属性が異なったり、パラメータの個数や属性が一致しない場合です。
    5. また C# と C++ は基本的には同じでも、書き方が違っていて、正しく書かないと行のエラーが消えません。
      例えば BitmapImage の設定を例にあげれば、次のようになります。
      【C#】
      Windows.UI.Xaml.Media.Imaging.BitmapImage bi;
      bi = new Windows.UI.Xaml.Media.Imaging.BitmapImage(new Uri("ms-appx:///ffx2s.jpg"));
      imgout.Source = bi;
      
      【C++】
      Windows::UI::Xaml::Media::Imaging::BitmapImage^ bi;
      Uri^ ui = ref new Uri("ms-appx:///ffx2s.jpg"); 
      bi = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(ui); 
      imgout->Source = bi;
      
    6. サンプルプログラムなどを検索しながら、APIの使い方を根気よく調べて下さい。
      ストアアプリのプログラムは基本的に Maneged Mode でコーデイングされているので、古参の方は慣れるまで苦労しそうです。
  24. エラーが指摘された行より前に原因があることも多く、行をさかのぼって調べて下さい。
    特に、未定義の名前(構造体なども含む)が使われると、エラーが山のように表示されます。
    また未定義の名前の行に「構文エラー:';'が'^'の前にありません。」が印字されることがあります。
    取り込んだヘッダが原因の場合もあり、ヘッダや using にも気を配りましょう。
  25. エラーメッセージで解りにくいのは「非値型はパブリックなデータ メンバー 'XXX' を持つことはできません」でしょうか?
    ref class は Maneged Mode です。
    UnManeged Mode の変数や関数を public: で宣言することは出来ません。
    例えば char * などを public: で宣言することは出来ません。
    但し、private: では使えるようなので、一度 private: に設定して試してみて下さい。
  26. 実行時のエラーでは、エラーを起こした行を特定することが先決です。
    行を特定するには OutputDebugString() などが効果を発揮します。
    この後で説明する Debug Note などを参考にして下さい。
  27. もっとも厄介なのがコンパイルが通っても実行時にエラーでこけることです。
    どうやらセグメントが異なるデータの演算に原因があるらしく、一旦現在の関数内にコピーしてから演算する方法を試して下さい。
    また Dirext3D に於いて World Matrix や Local Matrix が使えなくなっているようで、モデルの描画方法も異なります。
    16アラインメントに関しても不可解な現象が起こっています。
    アラインメントを調整する為にデータ領域の最後に次の領域を定義してみました。
    この行をコメントにすると実行時こけることを確認しています。
        DirectX::XMMATRIX   dummy;
    
  28. リソースの入力で注意が必要なことは、従来のようにディスク上のデータファイルに自由にアクセス出来ないことです。
    データファイルをプロジェクトのフォルダに格納して、リソースとして加えて下さい。
    (Picker を使うと、全てのフォルダにアクセス出来るようです。)
    画像はプロジェクトに加えるとリソースとして認識されますが、*.dat などは認識されません。
    ソリューションエクスプローラでプロジェクトに組み込むときは、右クリックから Build Action に Content を設定して下さい。
    install folder などを参考にして下さい。
  29. 非同期処理に付いても注意が必要です。
    Windows8 からは積極的に MultiTask を使って平行処理(マルチタスク)でプログラムされています。
    そのために従来では考えられないような現象が起こっています。
    同じプログラムを同じように起動しても、正常に実行されるときと、エラーで中断することがありました。
    また一度目は正常に実行されても、繰り返すとエラーになる現象にも遭遇しています。
    本当の原因は不明ですが、例えば2度目からはキャシュが効いてすぐに処理が終わるなどが考えられます。
    また同時に進行するタスクのタイミングに原因があるかも知れません。
    タスクを使うときは、同期を取る必要があるか否かも考慮しなければなりません。
  30. ストアアプリは、従来の .NET Framework のものでは無く、新しい WinRT という API(C++/CX)を利用しています。
    従って、プログラミングで戸惑うこともしばしばです。
    Win8 String などを参考にして下さい。
  31. ストアアプリで比較的プログラミングが楽なのは「C#」でしょうか。
    スタイルは異なりますが、比較的従来の言語仕様と似ています。
    いずれにしても、満足にプログラムが組めるようになるまでの道のりは険しいようです。 (^_^;)

    DirectX のエラー

  32. 基本的にソースコードに赤の下線が表示されるときはエラーの指摘ですが、ヘッダーファイルの解析が終わると消える場合があります。
    その場合は何の問題もありません。
    またソースを修正した直後では赤の下線が消えないことがあります。
    他のソースに切り替えて戻ると下線が消える現象を確認しています。
  33. DirectX のシステム関係のヘッダーファイルが見つからないエラーが表示されることがあります。
    正しく書かれているのに、このエラーが表示されるときは諦めて下さい。
    主な原因は古くなって廃止された機能です。
    古いシステムからヘッダーファイルをコピーすれば動く場合もありますが、あまりお勧めできません。
  34. 取得したリソースを開放せずに終了しようとしたときに表示されるメッセージボックスです。

  35. assert(pDevice != NULL); で pDevice が NULL のときに表示されるメッセージボックスです。

  36. V_RETURN(g_MultiAnim.Setup(pd3dDevice,L"tiny_4.x")); でエラーが発生したときに表示されるメッセージボックスです。
    今回のエラーの原因は X-FILE名で、正しくは V_RETURN(g_MultiAnim.Setup(pd3dDevice,L"tiny_4anim.x")); でした。

  37. 次のエラーが表示されて起動出来ません。
    Failed create the Direct3D device
    
    主にソースプログラムに原因があるのですが、一度 Release Mode でコンパイルしてみて下さい。
    詳細は Windows8+DirectX10 を参照して下さい。

*********************************************************************************************

【賞味期限が切れた説明を移動します】


    Visual Studio の 設定

  1. Unicode で MessageBox() を表示するプログラムです。
    VC++ の Unicode の設定は [プロジェクト][プロパティ][構成プロパティ][全般]から文字セットに 「Unicode 文字セットを使用する」を選択します。
    /*********************************/
    /*★ Unicode を使う    前田 稔 ★*/
    /*********************************/
    #include    <windows.h>
    WCHAR       str1[80] = L"WCHAR[] で宣言";
    wchar_t     str2[80] = L"wchar_t[] で宣言";
    
    //★ Windows Main 関数
    int  WINAPI  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
    {
        MessageBox(NULL,str1,L"Message Box",MB_OK);
        MessageBox(NULL,str2,L"Message Box",MB_OK);
        return 0;
    }
    
  2. tchar.h を取り込んで _T を使うと、マルチバイトの時は8ビットで、Unicode の時は16ビットでキャストしてくれます。
    マルチバイトで _T を使って MessageBox() を表示してみましょう。
    VC++ の MultiByte の設定は [プロジェクト][プロパティ][構成プロパティ][全般]から文字セットに 「マルチバイト文字セットを使用する」を選択します。
    /***********************************/
    /*★ MultiByte を使う    前田 稔 ★*/
    /***********************************/
    #include    <windows.h>
    #include    <tchar.h>
    LPSTR       str1 = "LPSTR で宣言";
    LPSTR       str2 = _T("LPSTR で宣言");
    
    //★ Windows Main 関数
    int  WINAPI  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
    {
        MessageBox(NULL,_T("MultiByte / Unicode Program"),_T("Message Box"),MB_OK);
        MessageBox(NULL,str1,str2,MB_OK);
        return 0;
    }
    
  3. Unicode で _T を使って MessageBox() を表示します。
    VC++ の Unicode の設定は [プロジェクト][プロパティ][構成プロパティ][全般]から文字セットに 「Unicode 文字セットを使用する」を選択します。
    /*********************************/
    /*★ Unicode を使う    前田 稔 ★*/
    /*********************************/
    #include    <windows.h>
    #include    <tchar.h>
    
    LPWSTR      str3 = L"LPWSTR で宣言";
    LPWSTR      str4 = _T("LPWSTR で宣言");
    
    //★ Windows Main 関数
    int  WINAPI  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
    {
        MessageBox(NULL,_T("MultiByte / Unicode Program"),_T("Message Box"),MB_OK);
        MessageBox(NULL,str3,str4,MB_OK);
        return 0;
    }
    

    MultiByte Note

  4. Shift-JIS では、1バイトコード(8 bit)と2バイトコード(16 bit)が混在しています。
    第1バイトが 81-9F ならびに E0-FC で始まるコードは2バイトコード(ひらかな, 漢字など)です。
    このとき、第2バイトは 40-7E ならびに 80-FC で構成されます。
  5. ディレクトリの区切り文字として \(5C) が使われます。
    C:\DATA\TEST\WK.TXT
    C:\HTML\PUBLIC\Windows.html
    また文字列のエスケープコードとしても \(5C) が使われます。
    従って文字列の中で \ を使うときは \\ と書きます。
    "C:\\DATA\\TEST\\WK.TXT"
    同様に文字列の中で " を使うときは \" と書きます。
    "\"TEXT DATA\""
  6. 「\」はエスケープコードなどと呼ばれ、\r は復帰コードで、\n は改行コードです。
    これはタイプライタの名残で、復帰は行の先頭に移動で、改行は次の行に用紙を送ります。
    復帰だけだと用紙は送られず、現在の行の上から重ねてタイプされます。
    改行だけだと次の行に用紙が送られるだけで、カラムの位置は現在のままです。
    つまり復帰と改行で次の行の先頭になる訳です。
    タイプライタでは、改行と逆方向に用紙を戻す機能も使われていました。
    さすがにパソコンでは、このコードは無いようです。 (^_^;)
    パソコンでも \r\n を組み合わせて使っていたのですが、最近は \n だけが使われるケースも良く見かけます。
    "TEXT DATA\r\n"
    "TEXT DATA\n"
    所が Windows で \n だけで保存すると、notepad.exe(メモ帳)で開いたときに改行されませんでした。
    Windows では \r\n で保存するのが良いようです。
    ちなみに、この確認は 2013/09/24 に次の環境で行いました。
    ・Windows8.1 評価版
    ・Microsoft Visual Studio Professional 2013 Preview - 日本語
    ・C:\Windows\System32\notepad.exe
  7. utf-16 を使っている場合は問題ないのですが、シフトJIS を使っている場合は次のような問題が発生します。
    パスを指定するときのエスケープコード(0x5C)の扱いで、全角文字の中に 5C を含む文字があります。
    次の例はほんの一部で、調べればもっと出てくるでしょう。
    文字 16進数
    \ 5C
    835C
    8D5C
    955C
    次のフルパスで指定されたファイル名を見て下さい。
    本来はディレクトリ名「c:\TMP\ソース\」としなければならないのに「ソ」の 5C をエスケープコードと判断する間違いを犯すことがあります。
    c:\TMP\ソース\テスト.TXT
    この処理は結構面倒で、全角/半角を判断しながら 5C を調べなければなりません。
    具体的な例は「前田稔のプログラム入門(C言語 Windows)/Windows Program Note/フルパスを調べる」を参照して下さい。
    ワイドキャラが使われるようになると、このような問題は起こらなくなります。
    Shift-JIS の詳しい説明は Shift_JIS を参照して下さい。
  8. シフトJIS は8ビット(256通り)のキャラクタコードで、非常にうまく日本語を使うコード体系でした。
    昔はメモリ(記憶装置)の値段も高く、いかに少ない容量で記憶するかも重要で、シフトJIS はその要望にもマッチしていました。
    余談にはなりますが、西暦年を4桁で表現するのは「もったいない」と「下2桁で記録」したために、2000年問題が起こったことは記憶に新しい所です。
    最近のようにメモリの値段が安くなり、飛躍的に容量がアップしたことを考えると、ワイドキャラは時代の流れかもしれません。 (^_^;)
  9. 2014/08/26 DirectX のプログラミングで思わぬエラーに遭遇しました。
    下記のデータ定義で g_Height が未定義になるのです。
    ソースファイルの TEXT CODE は UTF-8 を使っています。
    (Visual Studio を使うと規定値が UTF-8 で保存されるようになった?)
    int     g_Width = 1920;     // ウインドウの幅
    int     g_Height = 1080;    // ウインドウの高さ
    
    漢字の「幅」が原因のようで「はば」にすると解決しました。
    Unicode の 8 bit でもコード体系の問題は発生するようで、コメントと言えども日本語を使うときは注意が必要なようです。
新仕様

    開発環境

  1. 最近の開発環境は複雑怪奇です。
    Shift-JIS と Unicode だけでもややこしいのに Maneged Mode やらセキュリティの強化やら止めはストアアプリ(Windows10)です。
    特にC言語の開発環境には注意して下さい。
    開発環境が異なると説明どおりには動きません。
    私のページもそうでしょうが、ネットから検索したページも様々な開発環境が混在していて何が何やらわからない場合があります。
  2. vista からシステムの安定とセキュリティの強化から (^_^;) 不正(不用意)なメモリ領域へのアクセスを厳しく管理するようになりました。
    今まで問題なく通っていた string 関係の関数を中心として warning(警告)が発せられます。
    また CPU も16ビット→32ビット→64ビットの移行に伴い、古いプログラムが動かなくなっています。
    16ビットモードで作成されているプログラムやライブラリやDLLは使えないようで、32ビット(64ビット)で再コンパイルして下さい。
  3. warning(警告)が発せられる文字列関係の関数と対処の方法です。
    文字列処理は先に説明したストリング(String, string)で処理するのがベストです。
    今まで文字列操作は strcpy や lstrcpy 等を使っていましたが、これらはいとも簡単に確保したバッファ以上の領域に文字列を書き込んでしまいます。
    そこでオーバーランをしないよう考慮した関数が strsafe.h で提供されています。
    詳細は <strsafe.h> で追加された文字列操作関数について を参照して下さい。

    Shift_JIS の文字列操作例題

  4. [プロジェクト][プロパティ][構成プロパティ][全般]から文字セットに「マルチバイト文字セットを使用する」を選択します。
    文字列の長さを調べるプログラムです。
    オーバーランをしないよう考慮した関数は strsafe.h で定義されています。
    コンソールモードなのですが、LPSTR を使うので windows.h を取り込みます。
    StringCbLength と StringCchLength があるのですが、Shift-JIS では Cb(バイトで指定)を使います。
    str1 は26バイトで、str2 は13バイトでした。
    // strsafe Program File
    #include <windows.h>    //LPSTR
    #include <stdio.h>
    #include <strsafe.h>
    #include <conio.h>
    
    void  main()
    {
        char   str1[32] = "Unicode の文字列長を調べる";
        LPSTR  str2 = "LPWSTR で宣言";
        size_t leng;
    
        if (StringCbLength(str1, 32, &leng) != 0)
                printf("str1 Error\r\n");
        else    printf("str1= %d\r\n", leng);
        if (StringCbLength(str2, 24, &leng) != 0)
                printf("str2 Error\r\n");
        else    printf("str2= %d\r\n", leng);
        _getch();
    }
    
  5. sou から des に文字列をコピーします。
    des は \0 を含めて13バイト必要です。
    // strsafe Program File
    #include <windows.h>    //LPSTR
    #include <stdio.h>
    #include <strsafe.h>
    #include <conio.h>
    
    void  main()
    {
        LPSTR  sou = "LPSTR で宣言";
        char   des[13];
    
        if (StringCbCopy(des, 13, sou) != 0)
                MessageBox(NULL,"Cb Copy Error","Error",MB_OK);
        else    MessageBox(NULL,des,"Copy",MB_OK);
    }
    
  6. des に文字列を連結します。
    des は改行コードを含めて26バイトになります。
    OutputDebugString は Shift-JIS でも Unicode でも Windows8 でも使える関数で、出力ウインドウに印字されます。
    // strsafe Program File
    #include <windows.h>    //MessageBox
    #include <stdio.h>
    #include <strsafe.h>
    #include <conio.h>
    
    void  main()
    {
        char   des[30] = "LPSTR で宣言\r\n";
        char   work[64];
        size_t leng;
    
        if (StringCbCat(des, 30, "連結文字列\r\n") != 0)
            MessageBox(NULL,"CbCat Error","Error",MB_OK);
        else
        {
            StringCbLength(des, 30, &leng);
            if (StringCbPrintf(work, 64, "%s (%d)\r\n", des, leng) != 0)
                MessageBox(NULL,"CbPrintf Error","Error",MB_OK);
            else
            {
                OutputDebugString(work);
                MessageBox(NULL,work,"CbCat",MB_OK);
            }
        }
    }
    

    Unicode の文字列操作例題

  7. [プロジェクト][プロパティ][構成プロパティ][全般]から文字セットに「Unicode 文字セットを使用する」を選択します。
    文字列の長さを調べるプログラムです。
    オーバーランをしないよう考慮した関数は strsafe.h で定義されています。
    コンソールモードなのですが、WCHAR LPWSTR を使うので windows.h を取り込みます。
    StringCbLength と StringCchLength があるのですが、Unicode では Cch(文字数で指定)を使います。
    str1 は17文字で、str2 は10文字でした。
    // strsafe Program File
    #include <windows.h>
    #include <stdio.h>
    #include <strsafe.h>
    #include <conio.h>
    
    void  main()
    {
        WCHAR   str1[24] = L"Unicode の文字列長を調べる";
        LPWSTR  str2 = L"LPWSTR で宣言";
        size_t  leng;
        if (StringCchLength(str1, 24, &leng) != 0)
                printf("str1 Error\r\n");
        else    printf("str1= %d\r\n", leng);
        if (StringCchLength(str2, 24, &leng) != 0)
                printf("str2 Error\r\n");
        else    printf("str2= %d\r\n", leng);
        _getch();
    }
    
  8. sou から des に文字列をコピーします。
    CbCopy で12バイトで実行するとエラーになります。
    CchCopy で12文字を指定すると正常にコピーされました。
    // strsafe Program File
    #include <windows.h>
    #include <stdio.h>
    #include <strsafe.h>
    #include <conio.h>
    
    void  main()
    {
        LPWSTR  sou = L"LPWSTR で宣言";
        WCHAR   des[12];
    
        if (StringCbCopy(des, 12, sou) != 0)
                MessageBox(NULL,L"Cb Copy Error",L"Error",MB_OK);
        else    MessageBox(NULL,des,L"Copy",MB_OK);
        if (StringCchCopy(des, 12, sou) != 0)
                MessageBox(NULL,L"Cch Copy Error",L"Error",MB_OK);
        else    MessageBox(NULL,des,L"Copy",MB_OK);
    }
    
  9. des に文字列を連結します。
    des は改行コードを含めて19文字(des=12, "連結文字列\r\n"=7)になります。
    OutputDebugString は Shift-JIS でも Unicode でも Windows8 でも使える関数で、出力ウインドウに印字されます。
    // strsafe Program File
    // 連結後の長さ19文字
    #include <windows.h>
    #include <stdio.h>
    #include <strsafe.h>
    #include <conio.h>
    
    void  main()
    {
        WCHAR   des[32] = L"LPWSTR で宣言\r\n";
        WCHAR   work[64];
        size_t  leng;
    
        if (StringCchCat(des, 32, L"連結文字列\r\n") != 0)
            MessageBox(NULL,L"CchCat",L"Error",MB_OK);
        else
        {
            OutputDebugString(des);
            StringCchLength(des, 32, &leng);
            if (StringCchPrintf(work, 64, L"%s (%d)", des, leng) != 0)
                MessageBox(NULL,L"CchPrintf Error",L"Error",MB_OK);
            else    MessageBox(NULL,work,L"Cat",MB_OK);
        }
    }
    

    vista 以降

  10. ちょっと古い話ですが、VS++2.0 から for の中で宣言した変数の有効範囲が変更になったようです。
    従来は for の中で宣言した変数は、二回目以降は宣言が不要でした。
    for (int i=0; i != j; i++)
    {
       ・・・
    }
    for (i=10; i != k; i--)
    {
       ・・・
    }
    
    VS++2.0 からは有効範囲が for の中に制限されたようで、二回目以降も宣言が必要です。
    for (int i=0; i != j; i++)
    {
       ・・・
    }
    for (int i=10; i != k; i--)
    {
       ・・・
    }
    
  11. warning(警告)が発せられる fopen() 関数です。
    FILE    *FI;           //FILE の定義
    if (!(FI= fopen(file,"rb")))    オープンエラー
    
    fopen_s() 関数を使って下さい。
    FILE    *FI;           //FILE の定義
    if (fopen_s(&FI,file,"rb")!=0)  オープンエラー
    
  12. ビットマップのデータを取得する次の関数を実行するとエラーダイアログが表示されます。
    vista では使えなくなったのでしょうか? (^_^;)
    GetDIBits(hdc,hbm,0,bm.bmHeight,imgbuf,(LPBITMAPINFO)&g_Bi,DIB_RGB_COLORS);
  13. 古いバージョンでコンパイルした LIB や DLL は使えません。
    ソースレベルでは、互換性があるようなのでコンパイルをやり直して下さい。
  14. Maneged Mode でコンパイルすると exe や dll ができますが、中身はネイティブコードではありません。
    Maneged Mode では Java と同様に、実際のマシンに依存しない中間言語(Intermediate Language)が作成されます。
    exe や dll の中にはこれが格納されています。
    ネイティブコードに比べて実行ファイルのサイズが随分小さくなっています。
    その分、実行速度が劣ると思われますが、最近のマシンスペックでは全く気になりません。
    中間言語の形式は ECMA(European Computer Manufacturers Association) で定められていて、 ECMA-335 として公開されているので誰でも見ることができます。
    Microsoft の ECMA C# and Common Language Infrastructure Standards にはWord形式のファイルもあるようです。
    Maneged Mode のプログラムを実行するには中間言語をネイティブコードに変換して実行する仕組みが必要になります。
  15. .NET Framework SDK に付いてる ildasm を使えば exe や dll の中に格納されているメタデータや中間言語を見ることができます。
    IL DASM は[スタート][すべてのプログラム][Microsoft][.NET][Framework SDK v2.0][Tools] から起動できます。
    ファイルメニューから *.exe を読み込み、MANIFEST をダブルクリックすると詳細が表示されます。
    また、[スタート][すべてのプログラム][Microsoft][.NET][Framework SDK v2.0][Tools]から CLR 専用の [Microsoft CLR デバッガ] を起動することができます。

    関数の戻り値

  16. 関数の目的により戻り値(Return Code)が確定している場合を除いて、関数の戻り値に付いて考察してみました。
    BOOL 型
    YES(TRUE) または NO(FALSE) を戻り値として返すときに使用します。
    シンボル
    TRUE
    FALSE
  17. メインプログラムのソースコードです。
    /*******************************/
    /*★ BOOL type       前田 稔 ★*/
    /*******************************/
    #include    <windows.h>
    char        buf[128];
    
    BOOL  aGTb(int a,int b)
    {   if (a>b)    return TRUE;
        return FALSE;
    }
    
    //★ Windows Main 関数
    int PASCAL  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
    {   BOOL    rc;
    
        rc= aGTb(3,8);
        wsprintf(buf,"BOOL[%d]  ",rc);
        if (rc==TRUE)   strcat(buf,"3>8 TRUE");
        else            strcat(buf,"3>8 FALSE");
        MessageBox(NULL,buf,"BOOL",MB_OK);
    
        rc= aGTb(8,3);
        wsprintf(buf,"BOOL[%d]  ",rc);
        if (rc)     strcat(buf,"8>3 TRUE");
        else        strcat(buf,"8>3 FALSE");
        MessageBox(NULL,buf,"BOOL",MB_OK);
        return 0;
    }
        
  18. LRESULT 型
    LONG type(32 bit) で結果を返すときに使用します。
    このタイプは比較的良く使われていて、TRUE/FALSE に変えて S_OK/S_FALSE などを使うことがあります。
    S_OK/S_FALSE は TRUE/FALSE とはリターン値が逆 (^_^; になっていることに注意して下さい。
    シンボル
    TRUE
    FALSE
    S_OK
    S_FALSE
  19. メインプログラムのソースコードです。
    /**********************************/
    /*★ LRESULT type       前田 稔 ★*/
    /*   S_OK==0    S_FALSE==1        */
    /**********************************/
    #include    <windows.h>
    char        buf[128];
    
    LRESULT  func(HINSTANCE hInst)
    {   if (LoadIcon(hInst,IDI_APPLICATION)==NULL)  return S_OK;
        return S_FALSE;
    }
    
    //★ Windows Main 関数
    int PASCAL  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
    {   LRESULT rc;
    
        rc= func(NULL);
        wsprintf(buf,"LRESULT[%d]  ",rc);
        if (rc==S_OK)   strcat(buf,"NULL S_OK");
        else            strcat(buf,"NULL S_FALSE");
        MessageBox(NULL,buf,"LRESULT",MB_OK);
    
        rc= func(hInst);
        wsprintf(buf,"LRESULT[%d]  ",rc);
        if (rc==S_OK)   strcat(buf,"hInst S_OK");
        else            strcat(buf,"hInst S_FALSE");
        MessageBox(NULL,buf,"LRESULT",MB_OK);
        return 0;
    }
    
  20. HRESULT 型
    HANDLE type(32 bit) で結果を返すときに使用します。
    HANDLE に限らず SYSTEM で非常に良く使われているタイプです。
    戻り値も多彩で (^_^; 様々な定義名が使われています。
  21. メインプログラムのソースコードです。
    /**********************************/
    /*★ HRESULT type       前田 稔 ★*/
    /**********************************/
    #include    <windows.h>
    char        buf[128];
    
    HRESULT  func(int n)
    {   switch(n)
        {   case 0: return FALSE;       //0
            case 1: return TRUE;        //1
            case 2: return S_OK;        //0
            case 3: return S_FALSE;     //1
            case 4: return NULL;        //0
        }
        return -1L;
    }
    
    //★ Windows Main 関数
    int PASCAL  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
    {   HRESULT rc;
        int     i;
    
        for(i=0; i<5; i++)
        {   rc= func(i);
            wsprintf(buf,"HRESULT[%d]  ",rc);
            MessageBox(NULL,buf,"HRESULT",MB_OK);
        }
        return 0;
    }
    
  22. FAILED
    HRESULT と組み合わせて FAILED/SUCCEEDED を使う時の注意です。
    FAILED/SUCCEEDED は次のように定義されていて、正か負かを判定するだけです。
    ☆SUCCEEDED, FAILED
    #define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
    #define FAILED(Status)    ((HRESULT)(Status) < 0)
    
  23. E_FAIL は FAILED を返す定義名です。
    シンボル
    FALSE
    TRUE
    S_OK
    S_FALSE
    NULL
    E_FAIL 0x80004005
  24. メインプログラムのソースコードです。
    /***************************************/
    /*★ HRESULT type  FAILED    前田 稔 ★*/
    /***************************************/
    #include    <windows.h>
    char        buf[128];
    
    HRESULT  func(int n)
    {   switch(n)
        {   case 0: return FALSE;   //NO(0)
            case 1: return TRUE;    //YES(1)
            case 2: return S_OK;    //成功(0)
            case 3: return S_FALSE; //失敗(1)
            case 4: return NULL;    //空のポインタ
            case 5: return E_FAIL;  //失敗(0x80004005)
            case 6: return 0XFFFF;
            case 7: return -10L;
        }
        return -1L;
    }
    
    //★ Windows Main 関数
    int PASCAL  WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
    {   HRESULT hr;
        int     i;
    
        for(i=0; i<9; i++)
        {   hr= func(i);
            wsprintf(buf,"NULL HRESULT[%d(%x)]  ",hr,hr);
            if (FAILED(hr))     strcat(buf,"失敗");
            if (SUCCEEDED(hr))  strcat(buf,"成功");
            MessageBox(NULL,buf,"HRESULT",MB_OK);
        }
        return 0;
    }
    
  25. Visual Studio には多くの Window や Tool Bar が用意されています。
    Visual C++ Ver 6.0 で目的のウインドウやツールが表示されていないときは、Visual Studio 内の非表示部分を右クリックして表示された一覧から望みのものをチェックして下さい。
    ツールバーの「表示」メニューから操作する方法が一般的です。
    説明の画像