📄 vscapview.cpp
字号:
int DestroyShiftWindow() {
if (hMouseCaptureWnd) ::DestroyWindow(hMouseCaptureWnd);
return 0;
}
///////////////////////// //////////////////
/////////////// Functions //////////////////
///////////////////////// //////////////////
static HANDLE Bitmap2Dib( HBITMAP hbitmap, UINT bits )
{
HANDLE hdib ;
HDC hdc ;
BITMAP bitmap ;
UINT wLineLen ;
DWORD dwSize ;
DWORD wColSize ;
LPBITMAPINFOHEADER lpbi ;
LPBYTE lpBits ;
GetObject(hbitmap,sizeof(BITMAP),&bitmap) ;
//
// DWORD align the width of the DIB
// Figure out the size of the colour table
// Calculate the size of the DIB
//
wLineLen = (bitmap.bmWidth*bits+31)/32 * 4;
wColSize = sizeof(RGBQUAD)*((bits <= 8) ? 1<<bits : 0);
dwSize = sizeof(BITMAPINFOHEADER) + wColSize +
(DWORD)(UINT)wLineLen*(DWORD)(UINT)bitmap.bmHeight;
//
// Allocate room for a DIB and set the LPBI fields
//
hdib = GlobalAlloc(GHND,dwSize);
if (!hdib)
return hdib ;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hdib) ;
lpbi->biSize = sizeof(BITMAPINFOHEADER) ;
lpbi->biWidth = bitmap.bmWidth ;
lpbi->biHeight = bitmap.bmHeight ;
lpbi->biPlanes = 1 ;
lpbi->biBitCount = (WORD) bits ;
lpbi->biCompression = BI_RGB ;
lpbi->biSizeImage = dwSize - sizeof(BITMAPINFOHEADER) - wColSize ;
lpbi->biXPelsPerMeter = 0 ;
lpbi->biYPelsPerMeter = 0 ;
lpbi->biClrUsed = (bits <= 8) ? 1<<bits : 0;
lpbi->biClrImportant = 0 ;
//
// Get the bits from the bitmap and stuff them after the LPBI
//
lpBits = (LPBYTE)(lpbi+1)+wColSize ;
hdc = CreateCompatibleDC(NULL) ;
GetDIBits(hdc,hbitmap,0,bitmap.bmHeight,lpBits,(LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
lpbi->biClrUsed = (bits <= 8) ? 1<<bits : 0;
DeleteDC(hdc) ;
GlobalUnlock(hdib);
return hdib ;
}
UINT RecordAVIThread(LPVOID pParam) {
int top=rcUse.top;
int left=rcUse.left;
int width=rcUse.right-rcUse.left+1;
int height=rcUse.bottom - rcUse.top + 1;
int fps=frames_per_second;
CString fileName("\\~temp.avi");
tempfilepath = GetTempPath () + fileName;
//Test the validity of writing to the file
//Make sure the file to be created is currently not used by another application
int fileverified = 0;
while (!fileverified)
{
OFSTRUCT ofstruct;
HFILE fhandle = OpenFile( tempfilepath, &ofstruct, OF_SHARE_EXCLUSIVE | OF_WRITE | OF_CREATE );
if (fhandle != HFILE_ERROR) {
fileverified = 1;
CloseHandle( (HANDLE) fhandle );
DeleteFile(tempfilepath);
}
else {
srand( (unsigned)time( NULL ) );
int randnum = rand();
char numstr[50];
sprintf(numstr,"%d",randnum);
CString cnumstr(numstr);
CString fxstr("\\~temp");
CString exstr(".avi");
tempfilepath = GetTempPath () + fxstr + cnumstr + exstr;
}
}
RecordVideo(top,left,width,height,fps,tempfilepath);
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// RecordVideo
//
// The main function used in the recording of video
// Includes opening/closing avi file, initializing avi settings, capturing frames, applying cursor effects etc.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int RecordVideo(int top,int left,int width,int height,int fps,const char *szFileName) {
LPBITMAPINFOHEADER alpbi;
AVISTREAMINFO strhdr;
PAVIFILE pfile = NULL;
PAVISTREAM ps = NULL, psCompressed = NULL;
AVICOMPRESSOPTIONS opts;
AVICOMPRESSOPTIONS FAR * aopts[1] = {&opts};
HRESULT hr;
WORD wVer;
char szTitle[BUFSIZE];
actualwidth=width;
actualheight=height;
wVer = HIWORD(VideoForWindowsVersion());
if (wVer < 0x010a){
generalErrorMsg(ID_ERR_ENCODER_TOO_OLD, ID_TITLE_MSGBOX_ERROR, MB_OK|MB_ICONSTOP);
return FALSE;
}
alpbi = NULL;
////////////////////////////////////////////////
// CAPTURE FIRST FRAME
////////////////////////////////////////////////
alpbi=captureScreenFrame(left,top,width, height,1);
////////////////////////////////////////////////
// TEST VALIDITY OF COMPRESSOR
//////////////////////////////////////////////////
if (selected_compressor > 0) {
HIC hic = NULL;
hic = ICOpen(compressor_info[selected_compressor].fccType, compressor_info[selected_compressor].fccHandler, ICMODE_QUERY);
if (hic) {
int newleft,newtop,newwidth,newheight;
int align = 1;
while (ICERR_OK!=ICCompressQuery(hic, alpbi, NULL))
{
//Try adjusting width/height a little bit
align = align * 2 ;
if (align>8) break;
newleft=left;
newtop=top;
int wm = (width % align);
if (wm > 0) {
newwidth = width + (align - wm);
if (newwidth>maxxScreen)
newwidth = width - wm;
}
int hm = (height % align);
if (hm > 0) {
newheight = height + (align - hm);
if (newheight>maxyScreen)
newwidth = height - hm;
}
if (alpbi) FreeFrame(alpbi);
alpbi=captureScreenFrame(newleft,newtop,newwidth, newheight,1);
}
//if succeed with new width/height, use the new width and height
//else if still fails ==> default to MS Video 1 (MSVC)
if (align == 1) {
//Compressor has no problem with the current dimensions...so proceed
//do nothing here
}
else if (align <= 8) {
//Compressor can work if the dimensions is adjusted slightly
left=newleft;
top=newtop;
width=newwidth;
height=newheight;
actualwidth=newwidth;
actualheight=newheight;
}
else {
compfccHandler = mmioFOURCC('M', 'S', 'V', 'C');
strCodec = CString(L_MS_VIDEO_1);
}
ICClose(hic);
}
else {
compfccHandler = mmioFOURCC('M', 'S', 'V', 'C');
strCodec = CString(L_MS_VIDEO_1);
//MessageBox(NULL,"hic default","note",MB_OK);
}
}//selected_compressor
/*
//Special Cases
//DIVX
if (compfccHandler==mmioFOURCC('D', 'I', 'V', 'X'))
{ //Still Can't Handle DIVX
compfccHandler = mmioFOURCC('M', 'S', 'V', 'C');
strCodec = CString(L_MS_VIDEO_1);
}
*/
//IV50
if (compfccHandler==mmioFOURCC('I', 'V', '5', '0'))
{ //Still Can't Handle Indeo 5.04
compfccHandler = mmioFOURCC('M', 'S', 'V', 'C');
strCodec = CString(L_MS_VIDEO_1);
}
////////////////////////////////////////////////
// Set Up Flashing Rect
////////////////////////////////////////////////
if (flashingRect) {
if (autopan)
pFrame->SetUpRegion(left,top,width,height,1);
else
pFrame->SetUpRegion(left,top,width,height,0);
pFrame->ShowWindow(SW_SHOW);
}
////////////////////////////////////////////////
// INIT AVI USING FIRST FRAME
////////////////////////////////////////////////
AVIFileInit();
//
// Open the movie file for writing....
//
strcpy(szTitle,L_AVI_MOVIE);
hr = AVIFileOpen(&pfile, szFileName, OF_WRITE | OF_CREATE, NULL);
if (hr != AVIERR_OK) goto error;
// Fill in the header for the video stream....
// The video stream will run in 15ths of a second....
_fmemset(&strhdr, 0, sizeof(strhdr));
strhdr.fccType = streamtypeVIDEO;// stream type
//strhdr.fccHandler = compfccHandler;
strhdr.fccHandler = 0;
strhdr.dwScale = 1;
strhdr.dwRate = fps;
strhdr.dwSuggestedBufferSize = alpbi->biSizeImage;
SetRect(&strhdr.rcFrame, 0, 0, // rectangle for stream
(int) alpbi->biWidth,
(int) alpbi->biHeight);
// And create the stream;
hr = AVIFileCreateStream(pfile, &ps, &strhdr);
if (hr != AVIERR_OK) goto error;
memset(&opts, 0, sizeof(opts));
aopts[0]->fccType = streamtypeVIDEO;
//aopts[0]->fccHandler = mmioFOURCC('M', 'S', 'V', 'C');
aopts[0]->fccHandler = compfccHandler;
aopts[0]->dwKeyFrameEvery = keyFramesEvery; // keyframe rate
aopts[0]->dwQuality = compquality; // compress quality 0-10,000
aopts[0]->dwBytesPerSecond = 0; // bytes per second
aopts[0]->dwFlags = AVICOMPRESSF_VALID | AVICOMPRESSF_KEYFRAMES; // flags
aopts[0]->lpFormat = 0x0; // save format
aopts[0]->cbFormat = 0;
aopts[0]->dwInterleaveEvery = 0; // for non-video streams only
//Ver 1.2
//
if ((compfccHandler == CompressorStateIsFor) && (compfccHandler != 0)) {
//make a copy of the pVideoCompressParams just in case after compression, this variable become messed up
if (MakeCompressParamsCopy(CompressorStateSize, pVideoCompressParams)) {
aopts[0]->lpParms = pParamsUse;
aopts[0]->cbParms = CompressorStateSize;
}
}
//The 1 here indicates only 1 stream
//if (!AVISaveOptions(NULL, 0, 1, &ps, (LPAVICOMPRESSOPTIONS *) &aopts))
// goto error;
hr = AVIMakeCompressedStream(&psCompressed, ps, &opts, NULL);
if (hr != AVIERR_OK) goto error;
hr = AVIStreamSetFormat(psCompressed, 0,
alpbi, // stream format
alpbi->biSize + // format size
alpbi->biClrUsed * sizeof(RGBQUAD));
if (hr != AVIERR_OK) goto error;
FreeFrame(alpbi);
alpbi=NULL;
DWORD timeexpended, frametime, oldframetime;
initialtime = timeGetTime();
initcapture = 1;
oldframetime = 0;
nCurrFrame = 0;
nActualFrame = 0;
if (autopan) {
panrect_current.left = left;
panrect_current.top = top;
panrect_current.right = left + width - 1;
panrect_current.bottom = top + height - 1;
}
//////////////////////////////////////////////
// Recording Audio
//////////////////////////////////////////////
if (recordaudio) {
InitAudioRecording();
StartAudioRecording(&m_Format);
}
//////////////////////////////////////////////
// WRITING FRAMES
//////////////////////////////////////////////
long divx, oldsec;
divx=0;
oldsec=0;
while (recordstate) { //repeatedly loop
if (initcapture==0) {
timeexpended = timeGetTime() - initialtime;
}
else {
frametime = 0;
timeexpended = 0;
}
//Autopan
if ((autopan) && (width < maxxScreen) && (height < maxyScreen)) {
POINT xPoint;
GetCursorPos(&xPoint);
int extleft = ((panrect_current.right - panrect_current.left)*1)/4 + panrect_current.left;
int extright = ((panrect_current.right - panrect_current.left)*3)/4 + panrect_current.left;
int exttop = ((panrect_current.bottom - panrect_current.top)*1)/4 + panrect_current.top;
int extbottom = ((panrect_current.bottom - panrect_current.top)*3)/4 + panrect_current.top;
if (xPoint.x < extleft ) { //need to pan left
panrect_dest.left = xPoint.x - width/2;
panrect_dest.right = panrect_dest.left + width - 1;
if (panrect_dest.left < 0) {
panrect_dest.left = 0;
panrect_dest.right = panrect_dest.left + width - 1;
}
}
else if (xPoint.x > extright ) { //need to pan right
panrect_dest.left = xPoint.x - width/2;
panrect_dest.right = panrect_dest.left + width - 1;
if (panrect_dest.right >= maxxScreen) {
panrect_dest.right = maxxScreen - 1;
panrect_dest.left = panrect_dest.right - width + 1;
}
}
else {
panrect_dest.right = panrect_current.right;
panrect_dest.left = panrect_current.left;
}
if (xPoint.y < exttop ) { //need to pan up
panrect_dest.top = xPoint.y - height/2;
panrect_dest.bottom = panrect_dest.top + height - 1;
if (panrect_dest.top < 0) {
panrect_dest.top = 0;
panrect_dest.bottom = panrect_dest.top + height - 1;
}
}
else if (xPoint.y > extbottom ) { //need to pan down
panrect_dest.top = xPoint.y - height/2;
panrect_dest.bottom = panrect_dest.top + height - 1;
if (panrect_dest.bottom >= maxyScreen) {
panrect_dest.bottom = maxyScreen - 1;
panrect_dest.top = panrect_dest.bottom - height + 1;
}
}
else {
panrect_dest.top = panrect_current.top;
panrect_dest.bottom = panrect_current.bottom;
}
//Determine Pan Values
int xdiff,ydiff;
xdiff = panrect_dest.left - panrect_current.left;
ydiff = panrect_dest.top - panrect_current.top;
if (abs(xdiff) < maxpan) {
panrect_current.left += xdiff;
}
else {
if (xdiff<0)
panrect_current.left -= maxpan;
else
panrect_current.left += maxpan;
}
if (abs(ydiff) < maxpan) {
panrect_current.top += ydiff;
}
else {
if (ydiff<0)
panrect_current.top -= maxpan;
else
panrect_current.top += maxpan;
}
panrect_current.right = panrect_current.left + width - 1;
panrect_current.bottom = panrect_current.top + height - 1;
alpbi=captureScreenFrame(panrect_current.left,panrect_current.top,width, height,0);
}
else
alpbi=captureScreenFrame(left,top,width, height,0);
if (initcapture==0) {
if (timelapse>1000)
frametime++;
else
frametime = (DWORD) (((double) timeexpended /1000.0 ) * (double) (1000.0/timelapse));
}
else
initcapture = 0;
fTimeLength = ((float) timeexpended) /((float) 1000.0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -