前回、このサイトでBMPの表示方法を質問させていただきました。
そのプログラムをいじり、画像処理を色々とやってみて面白いと思いまして、
最近あまり用途がないWebカメラを使って画像処理ができないか調べていたところ、
幾つかサイトがヒットしました。
それらのサイトを調べたところ、VFW(Video For Windows)を使うのが手っ取り早そう
ということで、今回Webカメラを使い、WindowsAPI上でリアルタイム映像を表示する
プログラムをサイトを見ながら少し改良しつつやってみたのですが、自己解決できそうにない
エラーがでているので、質問させていただきます。
3.プログラムを実行すると、以下のエラー文がでてきます。
指定されたファイルが見つかりません。
カメラ制御.exe の 0x77c3f9f2 で初回の例外が発生しました: 0xC0000008: An invalid handle was specified
4.一応、このプログラムを実行し、エラーを無視して実行するか、
デバックなしで実行をするとWebカメラの映像は表示されます。
ですが、今回の質問は、このエラーが危険であるかのかどうか。
また、どのように回避すればよいのかをご教授願えればありがたいです。
よろしくお願いいたします。
5.C及びC++言語の知識
変数,配列,関数,条件文などの基本的なことは理解しています。
ポインタは、まだ自信が持てるほどではありませんが理解しています。
メモリの動的確保は、理解はしていますが複雑な条件でのメモリリークは、少し心配です。
クラスの方は、まだ勉強が浅いので、継承とコピーコンストラクタなどがまだ使いこなせていませんが、
クラスの簡単な使い方は理解しています。
使用環境
Windows7 64bit
Microsoft Visual C++ 2010 Express
WindowsAPI
使用カメラ
Buffalo BSW3K04H USB PC Camera
ソースコード
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <commctrl.h>
#include "math.h"
#pragma comment(lib, "comctl32.lib")
#pragma comment( lib, "gdiplus.lib" )
#include <gdiplus.h>
#include <Gdiplusinit.h>
#include "resource.h"
#include <vfw.h>
#pragma comment(lib,"vfw32.lib")
using namespace Gdiplus;
// 定数
#define WINDOW_WIDTH (640) // ウィンドウの幅:640
#define WINDOW_HEIGHT (480) // ウィンドウの高さ:480
#define WINDOW_X ((GetSystemMetrics( SM_CXSCREEN ) - WINDOW_WIDTH ) / 2)
#define WINDOW_Y ((GetSystemMetrics( SM_CYSCREEN ) - WINDOW_HEIGHT ) / 2)
#define ID_MI 1000
GdiplusStartupInput gdip_SI;
ULONG_PTR gdip_Token;
// グローバル変数
HINSTANCE g_hInst; // インスタンスハンドル
HWND g_hDlg; // ダイアログボックスのハンドル
HWND hWndCap;
// プロトタイプ宣言
HWND Create(HINSTANCE hInst);
HWND CreatePushButton(HWND hWnd, int x, int y, int w, int h, LPCTSTR caption, int id);
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
void SetCamera( HWND hWnd )
{
//既に値が入っている場合はドライバ解放
if(!(hWnd==NULL))capDriverDisconnect( hWndCap );
RECT rect;
GetClientRect(hWnd,&rect);
hWndCap = capCreateCaptureWindow(
_T("Captrue Window"), // キャプチャウィンドウの名前
WS_CHILD | WS_VISIBLE, // ウィンドウスタイル このパラメータについてはここを見てください。
0, 0, // 表示位置
rect.right - rect.left, rect.bottom - rect.top,// ウィンドウサイズ
hWnd, // 親のハンドル NULL:親なしのウィンドウ
1);
if(hWndCap==NULL)MessageBox(hWnd,_T("hWndCapの値がNULLになっています。"), NULL, NULL);
capDriverConnect( hWndCap, 0 ); // チャンネル1に接続
capPreviewRate( hWndCap, 1 );
capPreview( hWndCap, TRUE );
// ビデオフォーマット取得
BITMAPINFO bmpinfo;
capGetVideoFormat(hWndCap,&bmpinfo,sizeof(BITMAPINFO));
}
// 開始位置
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int showCmd)
{
HWND hWnd;
MSG msg;
//GDI+ Start
GdiplusStartup(&gdip_Token, &gdip_SI, NULL);
g_hInst = hInst; // インスタンスハンドルをグローバル変数に保存しておく
// ウィンドウを作成する
hWnd = Create(hInst);
if (hWnd == NULL)
{
MessageBox(NULL, TEXT("ウィンドウの作成に失敗しました"), TEXT("エラー"), MB_OK);
return 1;
}
// ウィンドウを表示する
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
// メッセージループ
while (1)
{
BOOL ret = GetMessage(&msg, NULL, 0, 0); // メッセージを取得する
if (ret == 0 || ret == -1)
{
// アプリケーションを終了させるメッセージが来ていたら、
// あるいは GetMessage() が失敗したら( -1 が返されたら )、ループを抜ける
break;
}
else
{
if ((g_hDlg == NULL || !IsDialogMessage(g_hDlg, &msg)))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
//GDI+ 終了処理
GdiplusShutdown(gdip_Token);
return (int)msg.wParam;
}
// ウィンドウを作成する
HWND Create(HINSTANCE hInst)
{
WNDCLASSEX wc;
// ウィンドウクラスの情報を設定
wc.cbSize = sizeof(wc); // 構造体サイズ
wc.style = CS_HREDRAW | CS_VREDRAW; // スタイル
wc.lpfnWndProc = WndProc; // ウィンドウプロシージャ
wc.cbClsExtra = 0; // 拡張情報1
wc.cbWndExtra = 0; // 拡張情報2
wc.hInstance = hInst; // インスタンスハンドル
wc.hIcon = (HICON)LoadImage( // アイコン
NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hIconSm = wc.hIcon; // 子アイコン
wc.hCursor = (HCURSOR)LoadImage( // マウスカーソル
NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // ウィンドウ背景
wc.lpszMenuName = NULL; // メニュー名
wc.lpszClassName = TEXT("Default Class Name");// ウィンドウクラス名
// ウィンドウクラスを登録する
if (RegisterClassEx(&wc) == 0){ return NULL; }
// ウィンドウを作成する
return CreateWindow(
wc.lpszClassName, // ウィンドウクラス名
_T("camera" ), // タイトルバーに表示する文字列
WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX, // ウィンドウの種類
WINDOW_X, // ウィンドウを表示する位置(X座標)
WINDOW_Y, // ウィンドウを表示する位置(Y座標)
WINDOW_WIDTH, // ウィンドウの幅
WINDOW_HEIGHT, // ウィンドウの高さ
NULL, // 親ウィンドウのウィンドウハンドル
NULL, // メニューハンドル
hInst, // インスタンスハンドル
NULL // その他の作成データ
);
//*******************************************************
}
static HWND hButton1;
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
static DEVMODE devmode; // ディスプレイモード
static OPENFILENAME ofn = { 0 };
static TCHAR strCustom[256] = TEXT("Before files\0*.*\0\0");
switch (msg)
{
case WM_CREATE: // ウィンドウが作成されたとき
hButton1 = CreateWindow(
_T("BUTTON"), _T("ダイアログボックス"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
20, 20, 150, 30, hWnd, (HMENU)ID_MI, g_hInst ,NULL);
//カメラ設定関数の呼び出し
SetCamera(hWnd);
return 0;
case WM_COMMAND: // 項目が選択されたとき
switch (LOWORD(wp))
{
case MB_OK:
break;
case ID_MI:
//モードレスダイアログの定義
//MessageBox(hWnd, _T("ボタンが押されました"), _T("確認"), NULL);
//g_hDlg = CreateDialog(g_hInst, _T("IDD_DIALOG1"), hWnd, (DLGPROC)DlgProc);
break;
}
return 0;
case WM_PAINT:
break;
case WM_CLOSE: // ウィンドウが閉じられるとき
if(!(hWndCap == NULL))capDriverDisconnect( hWndCap );
break; // ウィンドウを閉じる処理はDefWindowProc()に任せる
case WM_DESTROY: // ウィンドウが破棄されるとき
// ダイアログボックスを破棄する
if(!(g_hDlg == NULL))DestroyWindow(g_hDlg);
if(!(hWndCap == NULL))capDriverDisconnect( hWndCap );
DestroyWindow(hWnd);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wp, lp);
}
// ダイアログプロシージャ
BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg){
case WM_INITDIALOG: // ダイアログボックスが作成されたとき
return TRUE;
case WM_COMMAND: // ダイアログボックス内の何かが選択されたとき
switch (LOWORD(wp))
{
case IDOK:
break;
}
return TRUE;
case WM_CLOSE: // ダイアログボックスが閉じられるとき
// ダイアログボックスを消す
DestroyWindow(g_hDlg);
return TRUE;
}
return FALSE; // DefWindowProc()ではなく、FALSEを返すこと!
}