ビデオ信号について *

日本ではNTSC方式と呼ばれるものが一般的。市販のキャプチャボードを用いれば、これをPCに動画や静止画として取り込むことができる。このためのソフトはボードに付属するケースが多いが、自作も可能。

DirectShow *

前に(猿真似の)キャプチャソフトを作ったが、多少知識がついたので、DirectShowを使ってもうちょっと汎用的なキャプチャができればいいなあと思って勉強開始。

link *

自作キャプチャソフト(Windows) *

習作なのでバグや恥ずかしい勘違い等のオンパレードなのでしょう。どなたかこの先読み進まれる方、この点に注意して下さい。

何をするものか *

キャプチャボードからビデオ信号を読み込み、静止画に保存する。Video For Windows という規格を用いているので、これに対応したデバイスならキャプチャボードやUSBカメラ等製品を問わず動作すると思われる(未確認)。Video For Windows は若干古めの規格で、時代的にはDirectShowの方が適切そうだったがややこしそうなのでやめた。

JPEG周りはIndependent JPEG Groupのコードを使用した。

本体 *

SDKで作成。

起動し、デバイスと静止画保存フォーマットを選べばメインの画面となる。左が現在キャプチャしている画面で、右が静止画用。

参考link *

メモ *

プレビューとオーバーレイ *

違いが良くわからんが、

てなところ?全く自身がない。

capPreviewしておくと、常にcapSetCallbackOnFrameで指定されたコールバックが呼ばれる。 Previewの度に呼ばれるのだから当り前。 逆にcapOverlayだとそうはならない。ここでコールバックを呼ぶにはcapGrabFrameかcapGrabFrameNoStopを使う。 NoStopの方じゃないと、描画領域の更新が止まってしまう。

ソース *

/////////////////////////////////////////////////////////////////////////////////////////
// hiCapture - capture and save images (not video) via VFW (Video For Windows) device  //
/////////////////////////////////////////////////////////////////////////////////////////
//
// Version 1.0 ('04 Jun, 30)
// Hirotake Itoh <hiroitoh@issp.u-tokyo.ac.jp>
//
// NOTES:
// * I'm no more than beginner and there may be lots bugs... use carefully.
// * Of course, no warranty
// * This program uses IJG works to deal with JPEG files. See "http://www.ijg.org/"
//
// REFERENCES:
// http://www.katto.comm.waseda.ac.jp/~katto/Class/GazoTokuron/code/videocapture.html
// http://black.sakura.ne.jp/~third/system/winapi/win.html
// http://www7.plala.or.jp/keny01/win32/pre/index.html
// http://www.kk.iij4u.or.jp/~kondo/bmp/index.html
// http://www2m.biglobe.ne.jp/~yasutaka/
//
#include <windows.h>
#include <stdio.h>
#include <vfw.h>
#include <commctrl.h>

#include "jpeg/jpeglib.h"
#include "resource.h"


////////////////
// prototypes //
////////////////
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // window procedure for the main window
LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr); // callback for the video frame
LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText);
BOOL CALLBACK TimerDlgProc(HWND hTimerDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);    // dialog procedure (device selection)
BOOL CALLBACK DeviceDlgProc(HWND hTimerDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);    // dialog procedure (timer)

void ShowBitmap(HWND hWnd);    // show a captured frame in bitmap format
int VideoInit(HWND hWnd);    // video initialization
int VideoClose();            // video housekeepings

int write_JPEG_file (char * filename, int quality);
int write_BMP_file (char * filename);



////////////
// macros //
////////////
#define MYWINDOWCLASS "hiCapture"
#define MYWINDOWTITLE "hiCapture - report bugs to: hiroitoh@issp.u-tokyo.ac.jp"
#define MAX_CAPDEVICE 10    // limited to 10
#define TIMERID 0    // can be any number



//////////////////////
// global variables //
//////////////////////
HINSTANCE hInst;        // this application instance
HWND hWndVideo;            // window for the video frame
HBITMAP hBitmapFrame;    // bitmap handle for the static image
BITMAPINFO bmpInfo;        // bitmap information of the video frame
BITMAPFILEHEADER bmfh;    // used when the program saves the bitmap
int vWidth, vHeight;    // width and height (in pixel) of the video frame
void *pPixelArray;        // pixel data of the grabbed frame
char DeviceName[MAX_CAPDEVICE][100];    // device name
BOOL IsTimerRunning = FALSE;    // used for timer
UINT TimerInterval = 60;        // used for timer (in second)
BOOL PreferJpeg = FALSE;    // format of the saved file



//////////////////////////////////////
// WinMain and main window settings //
//////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS myProg;
    hInst = hInstance;
    
    if (!hPreInst) {
        myProg.style            = CS_HREDRAW | CS_VREDRAW;
        myProg.lpfnWndProc        = WndProc;
        myProg.cbClsExtra        = 0;
        myProg.cbWndExtra        = 0;
        myProg.hInstance        = hInstance;
        myProg.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
        myProg.hCursor            = LoadCursor(NULL, IDC_ARROW);
        myProg.hbrBackground    = GetStockObject(WHITE_BRUSH);
        myProg.lpszMenuName        = MAKEINTRESOURCE(IDR_MENU1);
        myProg.lpszClassName    = MYWINDOWCLASS;
        if (!RegisterClass(&myProg))
            return FALSE;
    }

    hWnd = CreateWindow(
        MYWINDOWCLASS, MYWINDOWTITLE,    // class, title
        WS_OVERLAPPEDWINDOW,            // style
        CW_USEDEFAULT, CW_USEDEFAULT,    // horizontal and vertical positions
        CW_USEDEFAULT, CW_USEDEFAULT,    // width and height
        NULL, NULL,                        // parent, menu or child window identifiers
        hInstance,                        // application instance
        NULL                            // window creation data
        );

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (msg.wParam);
}



///////////////////////////
// main window procedure //
///////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    // error handling
    char errstr[100];
    int i;    // error code of VideoInit

    // window size
    RECT rWindow, rClient;
    int WidthOffset;  // (Window_region - Client_region).width
    int HeightOffset; // (Window_region - Client_region).height
    
    // file handling
    char filename[20];
    SYSTEMTIME stTime;


    switch (msg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_CREATE:
        i = VideoInit(hWnd);
        if(i != 0) {
            wsprintf(errstr, "Error in \"VideoInit\" (%d)", i);
            MessageBox(hWnd, errstr, "error", MB_OK);
            PostQuitMessage(0);
        }
        if(IDYES == MessageBox(hWnd,
            "Choose the format for the image saving.\nYes -> JPEG\nNo -> BMP",
            "image format", MB_YESNO)) PreferJpeg = TRUE;
        SendMessage(hWnd, WM_SIZE, 0, 0);
        break;
    case WM_SIZE:
        GetWindowRect(hWnd, &rWindow);
        GetClientRect(hWnd, &rClient);
        WidthOffset = (rWindow.right - rWindow.left) - rClient.right;
        HeightOffset = (rWindow.bottom - rWindow.top) - rClient.bottom + 1;

        SetWindowPos(hWnd, NULL, 0, 0,
            vWidth*2+WidthOffset, vHeight+HeightOffset,    // width and height
            SWP_NOMOVE | SWP_NOZORDER);
        SetWindowPos(hWndVideo, NULL, 0, 0,
            vWidth, vHeight,                            // width and height
            SWP_NOMOVE | SWP_NOZORDER);
        break;
    case WM_CLOSE:
        VideoClose();
        DestroyWindow(hWnd);
        break;
    case WM_PAINT:
        ShowBitmap(hWnd);
        break;
    case WM_TIMER:
        SendMessage(hWnd, WM_COMMAND, (WPARAM)ID_SNAPANDSAVEIMAGE, 0);
        break;
    case WM_COMMAND:

        switch(LOWORD(wParam)){

        case ID_SNAP:
            capGrabFrameNoStop(hWndVideo);
            InvalidateRect(hWnd, NULL, FALSE);
            break;
        case ID_SAVEIMAGE:
            // time
            GetLocalTime(&stTime);
            wsprintf(filename, "%02d%02d%02d_%02d%02d%02d",
               stTime.wYear-2000, stTime.wMonth, stTime.wDay,
               stTime.wHour, stTime.wMinute, stTime.wSecond);
            if(PreferJpeg) write_JPEG_file(filename, 95);    // decrease '95' to save space
            else write_BMP_file(filename);
            break;
        case ID_SNAPANDSAVEIMAGE:
            SendMessage(hWnd, WM_COMMAND, (WPARAM)ID_SNAP, 0);
            SendMessage(hWnd, WM_COMMAND, (WPARAM)ID_SAVEIMAGE, 0);
            break;
        case ID_TIMER:
            // 'TimerInterval' is the interval in seconds.
            // 0 means that the user doesn't want to use the timer.
            TimerInterval = DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOGTIMER), NULL, TimerDlgProc);
            if(IsTimerRunning) {            // if the timer is running,
               KillTimer(hWnd, TIMERID);    // stop it,
               IsTimerRunning = FALSE;        // and update flag
            }
            if(TimerInterval != 0) {                                    // if the user wants to use the timer,
               SetTimer(hWnd, TIMERID, TimerInterval * 1000, NULL);    // start it,
               IsTimerRunning = TRUE;                                    // and update flag
            }
            break;
        }

        return 0;
        
    }
    return(DefWindowProc(hWnd, msg, wParam, lParam));
    
}




//////////////////////////////
// dialog procedure (timer) //
//////////////////////////////
BOOL CALLBACK TimerDlgProc(HWND hTimerDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    // retrieve window handles for each controls
    const HWND hWndTimerCheck = GetDlgItem(hTimerDlg, IDC_CHECKTIMER);
    const HWND hWndTimerEdit = GetDlgItem(hTimerDlg, IDC_EDITINTERVAL);
    const HWND hWndTimerSpin = GetDlgItem(hTimerDlg, IDC_SPININTERVAL);
    int nResult;    // timer interval in second

    switch(uMsg){
    case WM_INITDIALOG:
        SendMessage(hWndTimerSpin, UDM_SETRANGE, 0, MAKELONG(10800,1));    // interval range: 1s - 10800s (3h)
        SendMessage(hWndTimerSpin, UDM_SETPOS, 0, MAKELONG(TimerInterval,0));            // set previous interval
        if(IsTimerRunning) SendMessage(hWndTimerCheck, BM_SETCHECK, BST_CHECKED, 0);    // set previous flag
        else SendMessage(hWndTimerCheck, BM_SETCHECK, BST_UNCHECKED, 0);                //
        return TRUE;
    case WM_COMMAND:

        switch(LOWORD(wParam)){

        case IDOK:
            if(BST_UNCHECKED == SendMessage(hWndTimerCheck, BM_GETCHECK, 0, 0)) nResult = 0;
            else nResult = SendMessage(hWndTimerSpin, UDM_GETPOS, 0, 0);
            // now nResult is same as new interval, or 0, in case the user doesn't want to use the timer.
            EndDialog(hTimerDlg, nResult);
            break;
        default:
            return FALSE;
        }

    default:
        return FALSE;
    }
    return TRUE;
}




///////////////////////////////
// dialog procedure (device) //
///////////////////////////////
BOOL CALLBACK DeviceDlgProc(HWND hDeviceDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

    const HWND hWndCombo = GetDlgItem(hDeviceDlg, IDC_COMBO1);
    int i;
    char tmpstr[100];

    switch(uMsg){
    case WM_INITDIALOG:
        // only valid devices are to be added to combobox
        for(i=0; i<MAX_CAPDEVICE; i++){
            if(0 != strcmp("none", DeviceName[i])){
               wsprintf(tmpstr, "id: %d, %s", i, DeviceName[i]);
               SendMessage(hWndCombo, CB_ADDSTRING, 0, (LPARAM)tmpstr);
            }
        }
        // anyway, select one
        SendMessage(hWndCombo, CB_SETCURSEL, 0, 0);
        return TRUE;
    case WM_COMMAND:
        switch(LOWORD(wParam)){
            case IDOK:
               // return device id#
               SendMessage(hWndCombo, WM_GETTEXT, sizeof(tmpstr), (LPARAM)tmpstr);
               sscanf(tmpstr, "id: %d,", &i);
               EndDialog(hDeviceDlg, i);
               break;
            default:
               return FALSE;
        }
    default:
        return FALSE;
    }
    return TRUE;
}






//////////////////////////
// Video initialization //
//////////////////////////
int VideoInit(HWND hWnd){

    int i;    // used to retrieve indices of available drivers
    int j=0;    // check the number of valid drivers
    char DeviceVersion[100];    // almost for tempral use
    BOOL bDriverDescription;    // whether the specified driver is available or not
    DWORD wSize;            // the size of the video format
    char VideoFormat[200];    // used only for user notification

    // capture window
    hWndVideo = capCreateCaptureWindow(
        "CapWindow",
        WS_CHILD | WS_VISIBLE,
        0,
        0,
        320,
        240,
        hWnd,
        0
        );
    if(hWndVideo == NULL) return -1;

    // callbacks
    capSetCallbackOnFrame(hWndVideo, FrameCallbackProc);
    capSetCallbackOnError(hWndVideo, ErrorCallbackProc);

    // driver
    for(i=0; i<MAX_CAPDEVICE; i++){
        bDriverDescription = capGetDriverDescription(
            i,
            (LPSTR)DeviceName[i], sizeof(DeviceName[i]),
            (LPSTR)DeviceVersion, sizeof(DeviceVersion)
            );
        if(!bDriverDescription){
            wsprintf(DeviceName[i],"none");
            //wsprintf(DeviceMessage, "The following device was found:\n%s", DeviceName[i]);
            //MessageBox(hWnd, DeviceMessage, "Device Notification", MB_OK);
        }
        else j++;
    }
    if(j == 0) return -6;    // no valid drivers
    
    i = DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOGDEVICE), NULL, DeviceDlgProc);
    capDriverConnect(hWndVideo, i);


    // picture format
    wSize = capGetVideoFormatSize(hWndVideo);
    if( !capGetVideoFormat(hWndVideo, &bmpInfo, wSize) ){
        DestroyWindow(hWndVideo);
        return -2;
    }
    if( bmpInfo.bmiHeader.biCompression != BI_RGB || bmpInfo.bmiHeader.biBitCount != 24){
        MessageBox(hWnd, "Sorry, only 24bit RGB. exitting...", "error", MB_OK);
        return -3;
    }
    vWidth = bmpInfo.bmiHeader.biWidth;
    vHeight = bmpInfo.bmiHeader.biHeight;
    wsprintf(VideoFormat, "Width: %d\nHeight: %d", vWidth, vHeight);
    MessageBox(hWnd, VideoFormat, "Size:", MB_OK);


    // prepare bitmap file header
    bmfh.bfType = 'B' + ('M'<<8);    // 'BM'
    bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);    // offset to pixel array
    bmfh.bfSize = bmfh.bfOffBits + bmpInfo.bmiHeader.biSizeImage;    // entire filesize


    // create bitmap handle
    // NOTE: Memory allocation and deallocation of the array for pixels (pPixelArray)
    //       are automatically done by CreateDIBSection and DeleteObject. In other words,
    //       'malloc' or 'free' for pPixelArray must NOT be done manually.
    hBitmapFrame = CreateDIBSection(NULL, &bmpInfo, DIB_RGB_COLORS, &pPixelArray, NULL, 0);
    if(hBitmapFrame == NULL){
        MessageBox(hWnd, "\"CreateDIBSection\" failed", "error", MB_OK);
        return -4;
    }


    // show currently captured image
    capOverlay(hWndVideo, TRUE);

    return 0;

}



////////////////////////
// Video housekeeping //
////////////////////////
int VideoClose(){

    // release callbacks
    capSetCallbackOnError(hWndVideo, NULL);
    capSetCallbackOnFrame(hWndVideo, NULL);

    // destroy the window
    DestroyWindow(hWndVideo);

    // release memory (i.e. bitmap handle)
    DeleteObject(hBitmapFrame);

    return TRUE;
}




////////////////////////////
// showing captured image //
////////////////////////////
void ShowBitmap(HWND hWnd){

    HDC hDC, hBuffer; // hBuffer is used for memory device context, in order to show bitmap image

    hDC = GetDC(hWnd);
    hBuffer = CreateCompatibleDC(hDC);
    SelectObject(hBuffer, hBitmapFrame);

    BitBlt(
        hDC,        // target DC
        vWidth+1, 0,    // x, y coordinates of the target
        vWidth,        // width of the transfering rectangle
        vHeight,    // height of the transfering rectangle
        hBuffer,    // source DC
        0, 0,        // x, y coordinates of the source
        SRCCOPY        // raster operation mode
        );
    
    DeleteDC(hBuffer);
    ReleaseDC(hWnd, hDC);
    return;
}




////////////////////////////////////////////////////////////////
// frame callback function, which retrieves raw captured data //
////////////////////////////////////////////////////////////////
LRESULT PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr) 
{ 
    memcpy(pPixelArray, lpVHdr->lpData, lpVHdr->dwBufferLength);
    return (LRESULT) TRUE ; 
} 



/////////////////////////////
// error callback function //
/////////////////////////////
LRESULT PASCAL ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText) 
{ 
    return (LRESULT) TRUE; 
} 




///////////////////////
// file saving (BMP) //
///////////////////////
int write_BMP_file (char * filename){
    HANDLE hfile;
    char FilenameWithExt[256];
    DWORD tmp;


    wsprintf(FilenameWithExt, "%s.bmp", filename);
    hfile = CreateFile(FilenameWithExt, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
    WriteFile(hfile, &bmfh, sizeof(bmfh), &tmp, NULL);
    WriteFile(hfile, &bmpInfo.bmiHeader, sizeof(bmpInfo.bmiHeader), &tmp, NULL);
    SetFilePointer(hfile, bmfh.bfOffBits, NULL, FILE_BEGIN);
    GdiFlush();
    WriteFile(hfile, pPixelArray, bmpInfo.bmiHeader.biSizeImage, &tmp, NULL);
    CloseHandle(hfile);
    return 0;

}


////////////////////////
// file saving (JPEG) //
////////////////////////
int write_JPEG_file (char * filename, int quality){

    // quality: 0(low)...100(high)  5-95 is useful range (from 'cjpeg.c')
    struct jpeg_compress_struct cinfo;
    struct jpeg_error_mgr jerr;
    FILE * outfile;        /* target file */
    JSAMPROW row_pointer[1];    /* pointer to JSAMPLE row[s] */
    int row_stride;        /* physical row width in image buffer */
    JSAMPLE * image_buffer;
    int i,j,k1,k2;
    unsigned char *temp;
    char FilenameWithExt[256];

    
    // allocate memory for image_buffer
    image_buffer = (JSAMPLE *)malloc(bmpInfo.bmiHeader.biSizeImage);
    if(image_buffer == NULL) return -1;
    
    //
    //                    | Windows BMP (see RGBQUAD) | what JPEG program wants |
    // -------------------+---------------------------+-------------------------+-
    //      color order   |   B,G,R,B,G,R,.......     |    R,G,B,R,G,B,........ |
    // -------------------+---------------------------+-------------------------+-
    //  vertical drawing  |  from bottom to top       |  from top to bottom     |
    // -------------------+---------------------------+-------------------------+-
    //
    // So we have to convert the pixel order of the source array to obtain nice JPEG image.
    // Otherwise, such as
    // memcpy(image_buffer, pPixelArray, bmpInfo.bmiHeader.biSizeImage);
    // a strange image will come.

    temp = (unsigned char *)pPixelArray;


    for(i=0; i< vHeight; i++) {
        k1 = i * 3 * vWidth;
        k2 = (vHeight - i - 1) * 3 * vWidth;
        for(j=0; j< 3*vWidth; j+=3) {
            *(image_buffer + k1 + j + 0) = *(temp + k2 + j + 2);
            *(image_buffer + k1 + j + 1) = *(temp + k2 + j + 1);
            *(image_buffer + k1 + j + 2) = *(temp + k2 + j + 0);
        }
    }

    // Step 1
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);

    // Step 2
    wsprintf(FilenameWithExt, "%s.jpg", filename);
    if ((outfile = fopen(FilenameWithExt, "wb")) == NULL) {
        fprintf(stderr, "can't open %s\n", FilenameWithExt);
        return -2;
    }
    jpeg_stdio_dest(&cinfo, outfile);


    // Step 3
    cinfo.image_width = vWidth;     /* image width and height, in pixels */
    cinfo.image_height = vHeight;
    cinfo.input_components = 3;        /* # of color components per pixel */
    cinfo.in_color_space = JCS_RGB;     /* colorspace of input image */

    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);

    // Step 4
    jpeg_start_compress(&cinfo, TRUE);

    // Step 5
    row_stride = vWidth * 3;    /* JSAMPLEs per row in image_buffer */

    while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
        (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
    }

    // Step 6
    jpeg_finish_compress(&cinfo);
    fclose(outfile);

    // Step 7
    jpeg_destroy_compress(&cinfo);

    // release image_buffer
    free(image_buffer);
    return 0;
}

リソーススクリプト *

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// ニ?ワク?resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
#ifdef _WIN32
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#endif //_WIN32

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

IDR_MENU1 MENU DISCARDABLE
BEGIN
    MENUITEM "snap",                        ID_SNAP
    MENUITEM "save",                        ID_SAVEIMAGE
    MENUITEM "snap&&save",                  ID_SNAPANDSAVEIMAGE
    MENUITEM "timer",                       ID_TIMER
END


#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1               ICON    DISCARDABLE     "icon1.ico"

/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
    IDD_DIALOGDEVICE, DIALOG
    BEGIN
 LEFTMARGIN, 7
 RIGHTMARGIN, 186
 TOPMARGIN, 7
 BOTTOMMARGIN, 39
    END

    IDD_DIALOGTIMER, DIALOG
    BEGIN
 LEFTMARGIN, 7
 RIGHTMARGIN, 129
 TOPMARGIN, 7
 BOTTOMMARGIN, 49
    END
END
#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_DIALOGDEVICE DIALOG DISCARDABLE  0, 0, 193, 46
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Choose device "
FONT 11, "Arial"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,65,25,50,14
    COMBOBOX        IDC_COMBO1,7,7,179,79,CBS_DROPDOWNLIST | CBS_SORT
|
     WS_VSCROLL | WS_TABSTOP
END

IDD_DIALOGTIMER DIALOG DISCARDABLE  0, 0, 136, 56
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Timer setting"
FONT 11, "Arial"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,92,10,27,24
    CONTROL         "Timer",IDC_CHECKTIMER,"Button",BS_AUTOCHECKBOX |
     WS_TABSTOP,24,7,35,10
    LTEXT           "Interval [sec]",IDC_STATICTIMER,7,20,43,11
    EDITTEXT        IDC_EDITINTERVAL,7,32,71,12,ES_AUTOHSCROLL
    CONTROL         "Spin2",IDC_SPININTERVAL,"msctls_updown32",
     UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY |
     UDS_ARROWKEYS,63,31,11,14
END

#endif    // ニ?ワク?resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

Last-modified: Tue, 07 Mar 2006 13:09:14 JST