27.二重起動防止とコマンドライン引数

 二重起動防止は、CreateMutex 関数か FindWindow 関数を使用すると可能です。

 ファイルをアイコンにドロップして起動したときのファイル名はコマンドライン引数で取得できますが、GetCommandLine関数か __argv、__argc 変数を使用できます。

 ただし、GetCommandLine 関数を使用する場合は、ファイル名分離関数を自作する必要があるでしょう。GetCommandLineW 関数を使用する場合は、CommandLineToArgvW 関数を使える。

 二重起動防止とコマンドライン引数の両方の機能を追加したいときは、コマンドライン引数を別のプロセス(この場合は、既に起動中のプログラム)に引き渡します。

LRESULT CALLBACK ProcWnd(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_COPYDATA:
        COPYDATASTRUCT *pcds;
        pcds = (COPYDATASTRUCT*) lParam;
        if(pcds->cbData > 0){
            Parse_CmdLine((char*)pcds->lpData);
        }
        break;
    
    case WM_CLOSE:
        DestroyWindow(hWnd);
        PostQuitMessage(0);
        break;
        
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR lpCmdLine, int nCmdShow)
{
    // 二重起動防止&コマンドライン引数引き渡し
    HWND hWnd = FindWindow(MYWNDCLASS, MYWNDTITLE);
    if(hWnd){
        COPYDATASTRUCT cds;
        ZeroMemory(&cds, sizeof(cds));
        cds.cbData = strlen(lpCmdLine)+1;
        cds.lpData = lpCmdLine;
        SendMessage(hWnd, WM_COPYDATA, NULL, (LPARAM)&cds);
        return 0;
    }
    
    // ウィンドウクラスの登録
    WNDCLASSEX wc;
    ...
    RegisterClassEx(&wc);
    
    // ウィンドウの作成
    hWnd = CreateWindowEx(...);
    
    // メッセージ ループ
    MSG        msg;
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

28.IE をウィンドウ内で表示する

 IE をATL関数を使用してウィンドウに貼り付けるサンプル。

 AtlAxWinInit() と CreateWindowEx() が無くても表示はできるが、動作不良(COPY&PASTE ができない)が発生する。

 atl.lib のリンク設定が必要。

#include <windows.h>
#include <atlbase.h>
#include <exdisp.h>

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static IWebBrowser2 *pWB = NULL;
    static HWND         hWB  = NULL;
    
    switch(uMsg)
    {
    case WM_CREATE:
        {
            CHAR        strURL[MAX_PATH] = "http://w5.abcoroti.com/~pgm/";
            WCHAR       wstrURL[MAX_PATH];
            VARIANT     vURL = {0}, vDummy = {0};
            LPUNKNOWN   pUk = NULL;
            LPOLESTR    pProgID = NULL;
            CHAR        strPrgID[256];
            HINSTANCE   hInst = ((LPCREATESTRUCT)lParam)->hInstance;
            
            CoInitialize(NULL);
            AtlAxWinInit();
            ProgIDFromCLSID(CLSID_WebBrowser, &pProgID);
            WideCharToMultiByte(CP_ACP, 0, pProgID, -1, strPrgID, sizeof(strPrgID), NULL, NULL);
            CoTaskMemFree(pProgID);
            hWB = CreateWindowEx(0, "AtlAxWin", strPrgID, WS_CHILD | WS_VISIBLE,
                                 0, 0, 0, 0, hWnd, NULL, hInst, NULL);
            AtlAxGetControl(hWB, &pUk);
            if(pUk){
                pUk->QueryInterface(IID_IWebBrowser2, (LPVOID *) &pWB);
                pUk->Release();
                pUk = NULL;
            }
            vURL.vt = VT_BSTR;
            MultiByteToWideChar(CP_ACP, 0, strURL, -1, wstrURL, sizeof(wstrURL));
            vURL.bstrVal = SysAllocString(wstrURL);
            if(pWB)
                pWB->Navigate2(&vURL, &vDummy, &vDummy, &vDummy, &vDummy);
            SysFreeString(vURL.bstrVal);
            VariantClear(&vURL);
            SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM) strURL);
        }
        return 0;
    case WM_SIZE:
        MoveWindow(hWB, 0, 0, LOWORD(lParam), HIWORD(lParam), FALSE);
        return 0;
    case WM_CLOSE:
        if(pWB){
            pWB->Stop();
            pWB->Release();
            pWB = NULL;
        }
        DestroyWindow(hWnd);
        CoUninitialize(); // 本来は、メインウィンドウを閉じてメッセージループを抜けた後に記述する
        PostQuitMessage(0);
        return 0;
    default:
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

29.フラッシュをウィンドウ内で表示する

 Macromedia Flash をATL関数を使用してウィンドウに貼り付けるサンプル。

 Flash9d.ocx のCLSIDや名前空間名、メンバ、メソッド等は、ATL関数を記述しないでコンパイルすると生成される Flash9d.tlh というヘッダファイルに記述されている。

 atl.lib のリンク設定が必要。
 Flash9d.ocx はソースファイルと同じフォルダにコピーしておく。

#include <windows.h>
#include <atlbase.h>
#import ".\\Flash9d.ocx"

using namespace ShockwaveFlashObjects;

LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    static IShockwaveFlash  *pFlash = NULL;
    static HWND             hFlash  = NULL;
    
    switch(uMsg)
    {
    case WM_CREATE:
        {
            LPUNKNOWN   pUk = NULL;
            LPOLESTR    pProgID = NULL;
            CHAR        strPrgID[256];
            HINSTANCE   hInst = ((LPCREATESTRUCT)lParam)->hInstance;
            
            CoInitialize(NULL);
            AtlAxWinInit();
            ProgIDFromCLSID(__uuidof(ShockwaveFlash), &pProgID);
            WideCharToMultiByte(CP_ACP, 0, pProgID, -1, strPrgID, sizeof(strPrgID), NULL, NULL);
            CoTaskMemFree(pProgID);
            hFlash = CreateWindowEx(0, "AtlAxWin", strPrgID, WS_CHILD | WS_VISIBLE,
                                    0, 0, 0, 0, hWnd, NULL, hInst, NULL);
            AtlAxGetControl(hFlash, &pUk);
            if(pUk){
                pUk->QueryInterface(__uuidof(IShockwaveFlash), (LPVOID *) &pFlash);
                pUk->Release();
            }
            if(pFlash){
                pFlash->put_Movie(L"c:\\sample.swf");
                pFlash->Play();
            }
        }
        return 0;
    case WM_SIZE:
        MoveWindow(hFlash, 0, 0, LOWORD(lParam), HIWORD(lParam), FALSE);
        return 0;
    case WM_CLOSE:
        if(pFlash){
            pFlash->Stop();
            pFlash->Release();
            pFlash = NULL;
        }
        DestroyWindow(hWnd);
        CoUninitialize(); // 本来は、メインウィンドウを閉じてメッセージループを抜けた後に記述する
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}


30.WebサーバにあるHTMLを取得する

 リモートホストのテキストファイルの内容を読み込んで表示する。

 wininet.lib のリンク設定が必要。

#include <windows.h>
#include <wininet.h>

void Read_Html(HWND hWnd)
{
    HINTERNET   hSession,hFile;
    DWORD       dwRead;
    char        szTemp[1024];
    char        strURL[] = "http://w5.abcoroti.com/~pgm/";
    HDC         hDC;
    int         ct = 0;

    hSession = InternetOpen("WinInet Sample",
                            INTERNET_OPEN_TYPE_PRECONFIG,
                            NULL,
                            NULL,
                            0);

    hFile = InternetOpenUrl(hSession,
                            (LPCTSTR)strURL,
                            NULL,
                            0,
                            INTERNET_FLAG_DONT_CACHE,
                            0);

    hDC = GetDC(hWnd);
    while (InternetReadFile(hFile, (LPVOID)szTemp, 1024, &dwRead))
    {
        if (!dwRead) break;
        TextOut(hDC,0,ct,szTemp,strlen(szTemp));
        ct += 20;
    }

    InternetCloseHandle(hSession);
    InternetCloseHandle(hFile);

    ReleaseDC(hWnd,hDC);
}

31.ダイアログにActiveXコントロールを表示

 ダイアログに、MSFlexGrid Control を表示するサンプル

 atl.lib のリンク設定が必要。
 リソースエディタで、作成したダイアログを右クリック→[ActiveX コントロールの挿入]→[Microsoft FlexGrid Control] を選択。

#include <windows.h>
#include <atlbase.h>
#include "resource.h"
#import <MSFLXGRD.OCX> exclude("OLEDropEffectConstants")
using namespace MSFlexGridLib;

int CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static IMSFlexGrid  *pFG = NULL;
    switch (uMsg)
    {
    case WM_INITDIALOG:
        {
            LPUNKNOWN   pUk = NULL;
            AtlAxGetControl(GetDlgItem(hDlg, IDC_MSFLEXGRID1), &pUk);
            if(pUk){
                pUk->QueryInterface(__uuidof(IMSFlexGrid), (LPVOID*) &pFG);
                pUk->Release();
            }
            if(!pFG)
                break;
            pFG->put_Cols(4);
            pFG->put_Rows(3);
            _bstr_t bstr("ooooo");
            pFG->put_TextArray(0, bstr);
            pFG->put_TextArray(1, _bstr_t("abcdefg"));
            pFG->put_TextMatrix(1, 1, _bstr_t("あいうえお"));
        }
        break;
    case WM_COMMAND:
        switch(wParam)
        {
        case IDOK:
            SendMessage(hDlg,WM_CLOSE,0,0);
            break;
        case IDCANCEL:
            SendMessage(hDlg,WM_CLOSE,0,0);
            break;
        default:
            return FALSE;
        }
        break;
    case WM_CLOSE:
        if(pFG){
            pFG->Release();
            pFG = NULL;
        }
        DestroyWindow(hDlg);
        PostQuitMessage(0);
        break;
    default:
        return FALSE;
    }
    return TRUE;
}

int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    HWND hDlg;
    
    CoInitialize(NULL);
    hDlg = AtlAxCreateDialog(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc, NULL);
    ShowWindow(hDlg, nCmdShow);
    
    while(GetMessage(&msg, NULL, 0, 0)) {
        if (IsDialogMessage(hDlg, &msg)) continue;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    CoUninitialize();
    return msg.wParam;
}

32.GUID(CLSIDなど)の作成、表記方法の変更

 MSDNサンプルのguidgenをビルドして実行すると、
 作成されたCLSIDがクリップボードにコピーされる。

 おそらく、作成したCLSIDは、ActiveXコントロールを自作するときに使用する。

 MSDEV→[ツール]→[コントロールの登録]を実行するか
 Regsvr32.exe を実行して、そのCLSIDを記述した
 ライブラリをレジストリに登録して使用する。

 uuidgen.exe は、DirectShow のフィルターを作成するときに使う。
//{6F0D123B-BAD2-4167-A0D0-80224F25FABB} は下のguidの別の表記方法である

GUID guid = {0x6F0D123B, 0xBAD2, 0x4167, {0xA0, 0xD0, 0x80, 0x22, 0x4F, 0x25, 0xFA, 0xBB}};
char strGuid[64];
sprintf(strGuid,"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",guid.Data1,guid.Data2,guid.Data3,
                            guid.Data4[0],guid.Data4[1],guid.Data4[2],guid.Data4[3],guid.Data4[4],
                            guid.Data4[5],guid.Data4[6],guid.Data4[7]);

// 専用関数で変換する場合
LPOLESTR wstrGuid;
StringFromCLSID(*guid, &wstrGuid);
WideCharToMultiByte(CP_ACP, 0, wstrGuid, -1, strGuid, sizeof(strGuid), NULL, NULL);
CoTaskMemFree(wstrGuid);	

// 逆変換
GUID guid;
CLSIDFromString(OLESTR("{6F0D123B-BAD2-4167-A0D0-80224F25FABB}"), &guid);

// CLSIDが同じか調べる
BOOL bEqual = IsEqualCLSID(clsid1, clsid2);

// CLSIDを関数の引数にするときは、CLSIDよりはREFCLSIDを使う。
// GUIDやIIDもREFGUIDやREFIIDを使う。
// WTYPES.HでREFCLSIDは、const CLSID &と定義される。
void func(REFCLSID clsid)
{
}

main()
{
  CLSID clsid;
  func(clsid);
}

33.最小化、最大化から元のサイズに戻す

  // 元のサイズに戻す
  if(IsIconic(hWnd) || IsZoomed(hWnd)){
    ShowWindow(hWnd, SW_RESTORE);
  }
  
  // 最小化から元のサイズに戻す
  if(IsIconic(hWnd)){
    OpenIcon(hWnd);
  }
  
  // 最小化
  ShowWindow(hWnd, SW_MINIMIZE);    // または、CloseWindow(hWnd);
  
  // 最大化
  ShowWindow(hWnd, SW_MAXIMIZE);
  
  // 表示
  ShowWindow(hWnd, SW_SHOW);
  
  // 非表示
  ShowWindow(hWnd, SW_HIDE);
  
  // 有効化
  EnableWindow(hWnd, TRUE);
  
  // 無効化
  EnableWindow(hWnd, FALSE);
  
  // 表示されているか
  if(IsWindowVisible(hWnd)){
  }
  
  // 状態の取得
  WINDOWPLACEMENT wndpl;
  ZeroMemory(&wndpl, sizeof(wndpl));
  wndpl.length = sizeof(WINDOWPLACEMENT);
  GetWindowPlacement(hWnd, &wndpl);

34.マルチスレッド

 他の関数内のwhile()ループを終了させたい時やプログレス バーにファイル読み込みの進行状況を表示したい時は、マルチスレッドを使えば良い。
 マルチスレッドとは、複数のスレッドを使用したプログラム手法の事である。
 スレッドを使用すると、処理が速くなるというメリットもある。
 ただし、呼び出し元のスレッドは、呼び出したスレッドが終了する前に残りを処理してしまうため、スレッドがいつ終わったのか調べる必要がある場合もある。
 作成されたスレッドの関数が、再帰構造のときは、再帰の深度をカウントすると終了時が分かる。
 マルチスレッドは、MSDEV の設定後、process.h をインクルードし、_beginthread() でスレッドの作成、_endthread() で破棄を行う。スレッドは関数が終わると _endthread() が呼び出されるようになっているため、_endthread() は、途中終了したい場合にだけ使えば良い。
 _beginthread() は、関数の引数を1つしか渡せないが、構造体のポインタを引数にすると複数の値を渡す事が出来る。

 《MSDEV の設定》
 [プロジェクト] メニューの [設定] をクリックします。[プロジェクトの設定] ダイアログ ボックスで、[C/C++] タブをクリックします。[カテゴリ] ボックスの [コード生成] をクリックします。[使用するランタイム ライブラリ] ボックスの [マルチスレッド] をクリックします。[OK] をクリックします。
#include <windows.h>
#include <process.h>

struct LOOP
{
    int ct;             // 現在のループ回数
    int ct_max;         // ループの上限値
};

HWND    g_hWnd = NULL;
bool    g_bEnd = true;  // スレッドが終了したら true

void Count(void *pv)
{
    g_bEnd = false;
    LOOP *lp = (LOOP *)pv;
    lp->ct = 0;
    while(lp->ct < lp->ct_max && !g_bEnd){
        Sleep(10);
        (lp->ct) ++;
        InvalidateRect(g_hWnd, NULL, FALSE);
    }
    g_bEnd = true;
    InvalidateRect(g_hWnd, NULL, TRUE);
}

LRESULT CALLBACK ProcWnd(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    static LOOP lp = {0,0};
    
    switch (uMsg)
    {
    case WM_CREATE:
        g_hWnd = hWnd;
        return 0;
    case WM_KEYUP:
        switch (wParam)
        {
        case 'S':
            if(g_bEnd){
                lp.ct = 0;
                lp.ct_max = 1000;
                InvalidateRect(g_hWnd, NULL, TRUE);
                _beginthread(Count, 0, (void*)&lp);
            }
            break;
        case 'E':
            g_bEnd = true;
            break;
        }
        return 0;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hDC = BeginPaint(hWnd,&ps);
            char str1[256] = "[S]キーで開始、[E]キーで終了します";
            char str2[256] = "終了!";
            char str3[256] = "";
            TextOut(hDC, 0, 0, str1, strlen(str1));
            _itoa(lp.ct, str3, 10);
            TextOut(hDC, 0, 30, str3, strlen(str3));
            if(lp.ct > 0 && g_bEnd){
                TextOut(hDC, 0, 60, str2, strlen(str2));
            }
            EndPaint(hWnd,&ps);
        }
        return 0;
    case WM_CLOSE:
        DestroyWindow(hWnd);
        PostQuitMessage(0);
        return 0;
    default:
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

35.分割コンパイル

 message.cpp の外部変数と関数を main.cpp で使用する例。

 下の3つのファイルをプロジェクトに追加後、ビルドする。
 ヘッダファイルは追加しなくてもよい。
// message.h の内容
extern int g_ct;
void Set_Num(int num);


// message.cpp の内容
#include "message.h"
int g_ct = 0;
void Set_Num(int num){
    g_ct = num;
}


// main.cpp の内容
#include <windows.h>
#include "message.h"
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hInstPrev,LPSTR lpCmdLine,int nCmdShow)
{
    char s[4];
    Set_Num(100);
    itoa(g_ct,s,10);
    MessageBox(0,s,"",MB_OK);
    return 0;
}

36.再定義の回避

 自作ヘッダファイルが多い場合などに使用する
・未定義の場合にのみ定義したい場合。

----- ヘッダファイルなどで ---------------

#ifndef RED
#define RED    0xFF0000
#endif
-------------------------------------------


・ヘッダファイルの再読を防止したい場合。
 (定義済みであれば内容が処理されないことを利用する。
  分割コンパイルでは全てのヘッダファイルに書いた方が無難。
  _ABC_H_ はヘッダファイルごとに変える必要あり) ----- abc.h の内容 ------------------------ #ifndef _ABC_H_ #define _ABC_H_ // 内容をここに入れる。プリプロセッサは入れ子にできる。 #endif ----- main.c の内容 ------------------------ #include "abc.h"

37.指定された実行ファイルが実行できるか?

char result[256];
long r = (long) FindExecutable(sample.exe, "C:\\program1\\", result);

戻り値
32 以上               成功
0                     メモリ不足
31                    ファイルタイプが違う
ERROR_FILE_NOT_FOUND  指定されたファイル名がない
ERROR_PATH_NOT_FOUND  指定されたパスがない
ERROR_BAD_FORMAT      Win32アプリでないか、アイコンである


または、

BOOL GetBinaryType (

LPCTSTR lpApplicationName,// ファイル名へのポインタ

LPDWORD lpBinaryType// ファイルの種類を格納する変数へのポインタ

);


38.バージョン情報の表示

ShellAbout(hWnd, "タイトル", "著作権情報", LoadIcon(hInst,MAKEINTRESOURCE(IDI_ICON1)));

39.ファイルの読み書き(テキスト形式)

  // 保存
  
  #include <stdio.h>
  FILE *file;
  int  n = 12345;
  
  if((file=fopen("sample.txt","w"))==NULL){
    return 0;		
  }
  fprintf(file,"%d\n",n);
  fputs("ABCDEFG",file);
  fclose(file);
  
  
  // 読み込み
  
  ---------- 最大 256バイトで、1行ずつ読み込む場合 ----------
  #include <stdio.h>
  FILE *file;
  char s[256];
  
  if((file=fopen("sample.txt","r"))==NULL){
    return 0;		
  }
  // while(!feof(file)) 内で、rewind、fsetpos、fseek、clearerr
  // は使用しない
  while(!feof(file)){
    fgets(s,256,file);
    if(ss[strlen(ss)-1] == '\n'){
      ss[strlen(ss)-1] = '\0';
    }
  }
  fclose(file);
  
  ----- 全て一度に読み込む場合(\r\nは、\nに変換される) -----
  #include <io.h>
  #include <fcntl.h>
  int file;
  if((file=_open("sample.txt",_O_TEXT))==-1){
    return 0;
  }
  long size1 = _filelength(file);
  char *buf = new char [size1];
  int size2 = _read(file,buf,size1);
  buf[size2] = '\0';
  delete[] buf;
  _close(file);

40.ファイルの読み書き(バイナリ形式)

  // 読み書きに使うデータ
  typedef struct{
    int num;
    char str[64];
  }DATA;
  
  DATA dt[16];
  
  int ct = 5;
 
  for(int i=0;i<ct;i++){
    dt[i].num = i;
    strcpy(dt[i].str, "abc");
  }
  
  ------------------------------------ fopen関数を使う場合 --------------------------------
  
  #include <stdio.h>
  
  // 保存
  FILE	*file;
  if((file=fopen("sample.dat","wb"))==NULL){
    return 0;
  }
  // バイナリの書き込みにfprintf(),fputs() は使わない
  fwrite(&ct,sizeof(int),1,file);   // 数値ctを保存
  fwrite(&dt,sizeof(DATA),ct,file); // 配列dtを保存
  fclose(file);
  
  // 読み込み
  FILE	*file;
  if((file=fopen("sample.dat","rb"))==NULL){
    return 0;
  }
  // バイナリの読み込みにfscanf(),fgets() は使わない
  fread(&ct,sizeof(int),1,file);   // 数値ctの読み込み
  fread(&dt,sizeof(DATA),ct,file); // 配列dtの読み込み
  fclose(file);
  
  --------------------------------- CreateFile関数を使う場合 ------------------------------
  
  // 保存
  HANDLE  hFile;
  DWORD   dwWrite;
  hFile = CreateFile("sample.dat",GENERIC_WRITE,FILE_SHARE_WRITE,
                     NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  if(hFile == INVALID_HANDLE_VALUE){
    return 0;
  }
  WriteFile(hFile,&ct,sizeof(int),&dwWrite,NULL);
  WriteFile(hFile,dt,sizeof(DATA)*ct,&dwWrite,NULL);
  CloseHandle(hFile);
  
  // 読み込み
  HANDLE  hFile;
  DWORD   dwRead;
  hFile = CreateFile("sample.dat",GENERIC_READ,FILE_SHARE_READ,
                     NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  if(hFile == INVALID_HANDLE_VALUE){
    return 0;
  }
  ReadFile(hFile,&ct,sizeof(int),&dwRead,NULL);
  ReadFile(hFile,dt,sizeof(DATA)*ct,&dwRead,NULL);
  CloseHandle(hFile);

41.ファイルの読み込み(形式不問)

  ----- 全て一度に読み込む場合 -----
  
  HANDLE  hFile;
  DWORD   dwRead;
  hFile = CreateFile("sample.dat",GENERIC_READ,FILE_SHARE_READ,
                     NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  if(hFile == INVALID_HANDLE_VALUE){
    return 0;
  }
  DWORD size = GetFileSize(hFile, NULL);
  if(size > 0 && size != 0xFFFFFFFF){
    char *buf = new char [size];
    ReadFile(hFile,buf,size,&dwRead,NULL);
    delete[] buf;
  }
  CloseHandle(hFile);

42.ポインタで2次元配列の確保

 クラス内で使用すると解放時にメモリリークになるから注意。
 put_value() が2つあるのは、オーバーロードというプログラミング技法である。
 オーバーライドではない。
 
 この項目のサンプル コードは、CPPファイルでコンソール アプリとして作成する


#include <stdio.h>
#include <malloc.h>
#include <memory.h>

void put_value(int **ppn)
{
    int n[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
    int x,y;
    
    for(y=0;y<4;y++){
        for(x=0;x<4;x++){
            ppn[y][x] = n[y][x];
            printf(" %2d", ppn[y][x]);
        }
        putchar('\n');
    }
}

void put_value(int (*pn)[4])
{
    int n[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
    int x,y;
    
    for(y=0;y<4;y++){
        for(x=0;x<4;x++){
            pn[y][x] = n[y][x];
            printf(" %2d", pn[y][x]);
        }
        putchar('\n');
    }
}

// 2つ目が固定の場合(malloc)
void two_dimensional_arrays1()
{
    int (*pn)[4];
    
    pn = (int(*)[4]) malloc(sizeof(int)*4*4);
    put_value(pn);
    free(pn);
}

// 2つ目が固定の場合(new 演算子)
void two_dimensional_arrays2()
{
    int (*pn)[4];
    
    pn = new int [4][4];
    put_value(pn);
    delete[] pn;
}

// 両方とも可変の場合(malloc)
void two_dimensional_arrays3()
{
    int i;
    int **ppn;
    
    ppn = (int**) malloc(sizeof(int*)*4); // ←訂正(2012/1/6)
    for(i=0;i<4;i++){
        ppn[i] = (int*) malloc(sizeof(int)*4);
    }
    put_value(ppn);
    for(i=0;i<4;i++){
        free(ppn[i]);
    }
    free(ppn);
}

// 両方とも可変の場合(new 演算子)
void two_dimensional_arrays4()
{
    int i;
    int **ppn;
    
    ppn = new int* [4];
    for(i=0;i<4;i++){
        ppn[i] = new int [4];
    }
    put_value(ppn);
    for(i=0;i<4;i++){
        delete[] ppn[i];
    }
    delete[] ppn;
}

void main()
{
    // 2つ目が固定の場合(malloc)
    two_dimensional_arrays1();
    // 2つ目が固定の場合(new 演算子)
    two_dimensional_arrays2();
    // 両方とも可変の場合(malloc)
    two_dimensional_arrays3();
    // 両方とも可変の場合(new 演算子)
    two_dimensional_arrays4();
    
    printf("\nHit any key");
    getchar();
}