📄 camera_control.cpp
字号:
/*---------------------------------------------------------------
CST 238 GUI Project.
Windows interface to digital camera senior project.
Filename: camera_control.cpp
Compiler: MSVC 6.0
Author: Ryan Henderson hendersr@oit.edu
Overview
This program transfers images from the camera and displays them
in a window. The user can adjust color balance with some
sliders, stop and start image transfer and save the current
image to a bitmap. The taskbar shows progress of downloading
the next picture from the camera.
Files description
camera_control.cpp
Top level file that handles windows API messages for the menus,
dialogs, status bars and etc. It starts a thread to access the
camera, transfer raw image, and translate them to a bitmap.
Messages from the thread are processed to update the window.
hardware_interface.cpp
Connects directly with the hardware through the
XSTOOL / DriverLINX parallel port driver. Commands and addresses
are sent to the camera to start, stop a transfer. Data is read
from the camera and written to a raw buffer.
image_manip.cpp
Reads raw image buffer and translates it to a bitmap. Uses the
class defined in bitmap.cpp for formatting the bitmap. Adjusts
colors in the bitmap according to values set by the adjust
color sliders. image_manip has it's own raw buffer that it fills
from the hardware_interface raw buffer.
hi fills its buffer -> im copies that buffer -> hi fills it's
buffer again. Wouldn't want to fill, read from same buffer or
image will not contain consistant data.
Bitmap.cpp
Defines a bitmap with bitmap file-header and bitmap info-header
structs and a big Picture Data buffer.
Script1.rc, resource.h
Resource studio created files for menu, dialog boxes
Other files
XESS Corporation xstools 4.0 www.xess.com
Thank you Dave Van den Bout for answering my questions.
DriverLINX Port I/O Driver Interface
<cp> Copyright 1996 Scientific Software Tools, Inc.<nl>
Unified IO - C++ interface for industrial IO cards
Copyright (C) 2000, UAB "BBD SOFT" ( http://www.bbdsoft.com/ )
-------------------------------------------------------------------*/
#include <process.h>
#include <windows.h>
#include <stdlib.h>
#include <assert.h>
#include <strstrea.h>
#include <fstream.h>
#include <string>
#include <commctrl.h>
#include <Commdlg.h>
#include <afxres.h>
using std::string;
#include "hardware_interface.h"
#include "image_manip.h"
#include "mystructs.h"
#include "resource.h"
#define WM_FRAME_FINISHED WM_USER
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam);
BOOL CALLBACK CamCtrProc (HWND hDlg, UINT message, WPARAM wParam,
LPARAM lParam);
BOOL CALLBACK AboutProc (HWND hDlg, UINT message, WPARAM wParam,
LPARAM lParam);
HWND hDlgModeless;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdParam, int nCmdShow)
{
static char szAppName[] = "Camera Controller";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
HMENU hMenu;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon =
LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1));
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = NULL;
RegisterClassEx (&wndclass);
hMenu = LoadMenu (hInstance, MAKEINTRESOURCE( IDR_MENU1 ) );
hwnd = CreateWindow (szAppName, // window class name
"Image Window",
// window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
hMenu, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow (hwnd, nCmdShow);
UpdateWindow (hwnd);
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
/*******************************************************************
Thread to pull the image from the camera and translate it to
a bmp. Because this takes about 10 - 20s, this will keep the
app from freezing during this process.
Problem: the thread doesn't end... It's still using hi and im
when their destructors are being called. Need a way to
end the thread gracefully.
*******************************************************************/
void GetImageThreadProc (PVOID pVoid)
{
PPARAMS pparams;
pparams = (PPARAMS)pVoid;
while(true)
{
pparams->hi->DownloadImage(pparams->hwnd);
pparams->hi->GetRawBuffCpy(pparams->im->GetlpRawImage());
pparams->im->RawtoBMP(); //Optional width and height later
// pparams->im->WriteBMPFile("bmpout.bmp");
SendMessage(pparams->hwnd, WM_FRAME_FINISHED, 0, 0);
}
}
/*******************************************************************
WndProc Handles Messages
*******************************************************************/
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
TCHAR szBuffer[32];
static hardware_interface *hi;
static image_manip *im;
static Bitmap* pbmTemp;
static BITMAPINFO bmpinfo;
static int cxClient, cyClient;
static PARAMS threadParams;
static HINSTANCE hInst;
INITCOMMONCONTROLSEX cc;
static HWND hStatusBar, hwndParent;
PDRAWITEMSTRUCT pdi;
RECT rcProgressBar;
static float fPercentComplete;
static CAMCTR_DATA ccd;
static UINT iSelection = ID_CONTROL_GO;
static HMENU hMenu;
OPENFILENAME ofn;
static TCHAR strFileName[255];
switch (message)
{
case WM_COMMAND:
switch (LOWORD (wParam))
{
case ID_FILE_EXIT:
SendMessage(hwnd, WM_CLOSE, 0, 0);
return 0;
//Pop getsavefilename dialog, then write file
case ID_FILE_SAVE_AS:
strFileName[0] = '\0';
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = strFileName;
ofn.lpstrFileTitle = NULL;
ofn.Flags = OFN_OVERWRITEPROMPT;
ofn.hInstance = NULL;
ofn.lpstrFilter = "Bitmap Files (*.BMP)\0*.bmp\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrInitialDir= NULL;
ofn.lpstrDefExt = "bmp";
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
ofn.nMaxFile = 255;
ofn.lpstrTitle = NULL;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lCustData = 0L;
ofn.nMaxFileTitle = NULL;
GetSaveFileName(&ofn);
im->WriteBMPFile(ofn.lpstrFile);
return 0;
//Pop Adjust color dialog. Set hourglass cause this could
//take a while
case ID_ADJUST_COLORBALANCE:
DialogBoxParam(hInst, MAKEINTRESOURCE( IDD_DIALOG1 ), hwnd,
CamCtrProc, (LPARAM)&ccd );
im->SetColorAdj(ccd.rgbqAdj);
SetCursor(LoadCursor(NULL, IDC_WAIT));
im->RawtoBMP();
SetCursor(LoadCursor(NULL, IDC_ARROW));
InvalidateRect(hwnd, NULL, FALSE);
return 0;
case ID_CONTROL_GO:
CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
iSelection = LOWORD(wParam);
CheckMenuItem(hMenu, iSelection, MF_CHECKED);
SetEvent(hi->GethEventGoStop());
return 0;
//Cause hi to wait on event ... suspending itself
case ID_CONTROL_STOP:
CheckMenuItem(hMenu, iSelection, MF_UNCHECKED);
iSelection = LOWORD(wParam);
CheckMenuItem(hMenu, iSelection, MF_CHECKED);
ResetEvent(hi->GethEventGoStop());
return 0;
case ID_ABOUT_ABOUTCAMERACONTROL:
DialogBox(hInst, MAKEINTRESOURCE( IDD_ABOUT ), hwnd,
AboutProc );
return 0;
}
break;
//Send by hi
case WM_DOWNLOAD_STATUS:
fPercentComplete = *(float*)wParam;
InvalidateRect(hStatusBar, NULL, TRUE);
return 0;
//Owner draw status bar needs an update
case WM_DRAWITEM:
pdi = PDRAWITEMSTRUCT(lParam);
rcProgressBar = pdi->rcItem;
rcProgressBar.right = (float)cyClient * fPercentComplete;
rcProgressBar.top+=2;
rcProgressBar.bottom-=2;
//Just drawing it myself ... he he
FillRect(pdi->hDC, &rcProgressBar,
(HBRUSH)GetStockObject (BLACK_BRUSH));
return 0;
//Make status bar update in size too
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
SendMessage(hStatusBar, WM_SIZE, 0, lParam);
return 0;
//Setup, init, create etc.
case WM_CREATE:
hInst = ((LPCREATESTRUCT) lParam)->hInstance;
cc.dwSize = sizeof(cc);
cc.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx(&cc);
//Create memory for im and hi
im = new image_manip;
hi = new hardware_interface;
//Initial Color adjust values
ccd.rgbqAdj.rgbRed = 127;
ccd.rgbqAdj.rgbGreen = 127;
ccd.rgbqAdj.rgbBlue = 127;
im->SetColorAdj(ccd.rgbqAdj);
//Setup status bar
hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE,
"", hwnd, ID_STATUS_BAR);
SendMessage(hStatusBar, SB_SETTEXT, SBT_OWNERDRAW , (LPARAM)"");
//Grab a handle to the menu
hMenu = GetMenu(hwnd);
// Check if port opened ok
if (hi->OpenedOK() == false)
{
wsprintf(szBuffer, "Couldn't Open Port");
MessageBox (hwnd, szBuffer, "Error!",
MB_OK | MB_ICONINFORMATION);
SendMessage(hwnd, WM_CLOSE, NULL, NULL);
}
//Startup thread to read from pport
threadParams.hwnd = hwnd;
threadParams.hi = hi;
threadParams.im = im;
_beginthread(GetImageThreadProc, 0, &threadParams);
return 0;
//Force a repaint when frame finished
case WM_FRAME_FINISHED:
InvalidateRect(hwnd, NULL, TRUE);
return 0;
//Draw the bitmap onto the display. I tried to stretch the bmp to
//fit the client, but it looks really ugly
case WM_PAINT:
pbmTemp = im->GetBitmap();
bmpinfo.bmiHeader = *pbmTemp->pbih;
hdc = BeginPaint(hwnd, &ps);
SetDIBitsToDevice(
hdc,
0,
0,
pbmTemp->pbih->biWidth,
pbmTemp->pbih->biHeight,
0,
0,
0,
pbmTemp->pbih->biHeight,
pbmTemp->lpPixels,
&bmpinfo,
DIB_RGB_COLORS);
EndPaint (hwnd, &ps);
return 0;
//Nice Doggy... Make sure things shut down ok
case WM_DESTROY:
hi->EndThread();
WaitForSingleObject(hi->GethEventThreadDead(), 5*1000);
//Once everybody is done with it, delete it
if(hi != 0) delete hi;
if(im != 0) delete im;
PostQuitMessage (0);
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
/*******************************************************************
Helper function for CamCtrProc function
Sets the static text numbers below the sliders
*******************************************************************/
void UpdateBuddies(HWND *hCtrl, CAMCTR_DATA *pccd)
{
TCHAR szBuffer[32];
wsprintf(szBuffer, "%d", pccd->rgbqAdj.rgbRed);
SetWindowText(hCtrl[0], szBuffer);
wsprintf(szBuffer, "%d", pccd->rgbqAdj.rgbGreen);
SetWindowText(hCtrl[1], szBuffer);
wsprintf(szBuffer, "%d", pccd->rgbqAdj.rgbBlue);
SetWindowText(hCtrl[2], szBuffer);
}
/*******************************************************************
Dialog box proc for adjust colors. Sets up range for sliders
on init. Also sets the position of the sliders to where they
were left last. The sliders are upside down. If I created
them manually, I might be able to set the LEFTISDOWN param, but
it does not seem to be supported.
*******************************************************************/
BOOL CALLBACK CamCtrProc (HWND hDlg, UINT message, WPARAM wParam,
LPARAM lParam)
{
static HWND hwndParent, hCtrl[6];
static CAMCTR_DATA ccd, *pccd;
switch (message)
{
case WM_INITDIALOG:
pccd = (CAMCTR_DATA*) lParam;
ccd = *pccd;
hCtrl[0] = GetDlgItem(hDlg, IDC_SLIDERRED);
hCtrl[1] = GetDlgItem(hDlg, IDC_SLIDERGREEN);
hCtrl[2] = GetDlgItem(hDlg, IDC_SLIDERBLUE);
hCtrl[3] = GetDlgItem(hDlg, IDC_STATIC_REDVAL);
hCtrl[4] = GetDlgItem(hDlg, IDC_STATIC_GREENVAL);
hCtrl[5] = GetDlgItem(hDlg, IDC_STATIC_BLUEVAL);
UpdateBuddies(&hCtrl[3], pccd);
//Red
SendMessage(hCtrl[0], TBM_SETRANGE,
(WPARAM) TRUE, // redraw flag
(LPARAM) MAKELONG(0, 255)); // min. & max. positions
SendMessage(hCtrl[0], TBM_SETPOS,
(WPARAM) TRUE, // redraw flag
(LPARAM) ccd.rgbqAdj.rgbRed); // min. & max. positions
//Green
SendMessage(hCtrl[1], TBM_SETRANGE,
(WPARAM) TRUE, // redraw flag
(LPARAM) MAKELONG(0, 255)); // min. & max. positions
SendMessage(hCtrl[1], TBM_SETPOS,
(WPARAM) TRUE, // redraw flag
(LPARAM) ccd.rgbqAdj.rgbGreen); // min. & max. positions
//Blue
SendMessage(hCtrl[2], TBM_SETRANGE,
(WPARAM) TRUE, // redraw flag
(LPARAM) MAKELONG(0, 255)); // min. & max. positions
SendMessage(hCtrl[2], TBM_SETPOS,
(WPARAM) TRUE, // redraw flag
(LPARAM) ccd.rgbqAdj.rgbBlue); // min. & max. positions
return true;
case WM_VSCROLL:
//The scroll bars are upside down ...
ccd.rgbqAdj.rgbRed = SendMessage(hCtrl[0], TBM_GETPOS, 0, 0) ;
ccd.rgbqAdj.rgbGreen = SendMessage(hCtrl[1], TBM_GETPOS, 0, 0);
ccd.rgbqAdj.rgbBlue = SendMessage(hCtrl[2], TBM_GETPOS, 0, 0) ;
UpdateBuddies(&hCtrl[3], &ccd);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDCANCEL:
EndDialog(hDlg, FALSE);
return true;
case IDOK:
*pccd = ccd;
EndDialog(hDlg, FALSE);
return true;
}
}
return false;
}
/*******************************************************************
About Box. Doesn't do much of anything... here for future
feature support!
*******************************************************************/
BOOL CALLBACK AboutProc (HWND hDlg, UINT message, WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return true;
case WM_COMMAND:
if(LOWORD(wParam) == IDOK)
{
EndDialog(hDlg, FALSE);
return true;
}
}
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -