wxScreenshotMaker.h#pragma once #include <wx/wx.h> #ifdef __WXMAC__ #include <OpenGL/OpenGL.h> #endif class wxScreenshotMaker { public: wxScreenshotMaker(); ~wxScreenshotMaker(); wxBitmap GetScreenshot(); private: #ifdef __WXMAC__ int screenWidth; int screenHeight; CGLContextObj glContextObj; int rowSize; unsigned char * glBitmapData; unsigned char * glRowData; void InitOpenGL(); void GrabGLScreen(); void SwizzleBitmap(); void FinalizeOpenGL(); #endif };
wxScreenshotMaker.cpp#include "wxScreenshotMaker.h" #ifndef __WXMAC__ #include <wx/dcscreen.h> #else #include <CoreFoundation/CoreFoundation.h> #include <ApplicationServices/ApplicationServices.h> #include <OpenGL/gl.h> #endif wxScreenshotMaker::wxScreenshotMaker() #ifdef __WXMAC__ : screenWidth(0), screenHeight(0), glBitmapData(NULL), glRowData(NULL) #endif { #ifdef __WXMAC__ wxSize size = wxGetDisplaySize(); screenWidth = size.GetWidth(); screenHeight = size.GetHeight(); InitOpenGL(); #endif } wxScreenshotMaker::~wxScreenshotMaker() { #ifdef __WXMAC__ FinalizeOpenGL(); #endif } wxBitmap wxScreenshotMaker::GetScreenshot() { #ifndef __WXMAC__ wxScreenDC screenDC; wxBitmap bmp(screenDC.GetSize().GetWidth(), screenDC.GetSize().GetHeight()); wxMemoryDC mdc(bmp); mdc.Blit(0, 0, bmp.GetWidth(), bmp.GetHeight(), &screenDC, 0, 0); mdc.SelectObject(wxNullBitmap); return bmp; #else if(glBitmapData) { GrabGLScreen(); wxImage img = wxImage(screenWidth, screenHeight, glBitmapData, true); return wxBitmap(img.Copy()); } #endif } #ifdef __WXMAC__ void wxScreenshotMaker::InitOpenGL() { do { rowSize = screenWidth * 3; rowSize = (rowSize + 2) & ~2; glRowData = (unsigned char *)realloc(glRowData, rowSize); glBitmapData = (unsigned char *)realloc(glBitmapData, rowSize * screenHeight); bzero(glRowData, rowSize); bzero(glBitmapData, rowSize * screenHeight); CGDirectDisplayID display = CGMainDisplayID(); CGLPixelFormatObj pixelFormatObj ; GLint numPixelFormats; CGLPixelFormatAttribute attribs[] = { kCGLPFAFullScreen, kCGLPFADisplayMask, (CGLPixelFormatAttribute)0, /* Display mask bit goes here */ (CGLPixelFormatAttribute)0 }; attribs[2] = (CGLPixelFormatAttribute) CGDisplayIDToOpenGLDisplayMask(display); /* Build a full-screen GL context */ CGLChoosePixelFormat( attribs, &pixelFormatObj, &numPixelFormats ); if ( pixelFormatObj == NULL ) break; CGLCreateContext( pixelFormatObj, NULL, &glContextObj ) ; CGLDestroyPixelFormat( pixelFormatObj ) ; if ( glContextObj == NULL ) break; CGLSetCurrentContext( glContextObj ) ; CGLSetFullScreen( glContextObj ) ; } while(false); } void wxScreenshotMaker::FinalizeOpenGL() { CGLSetCurrentContext( NULL ); CGLClearDrawable( glContextObj ); CGLDestroyContext( glContextObj ); free(glRowData); free(glBitmapData); } void wxScreenshotMaker::GrabGLScreen() { glReadBuffer(GL_FRONT); /* Read framebuffer into our bitmap */ glFinish(); glPixelStorei(GL_PACK_ALIGNMENT, 3); glPixelStorei(GL_PACK_ROW_LENGTH, 0); glPixelStorei(GL_PACK_SKIP_ROWS, 0); glPixelStorei(GL_PACK_SKIP_PIXELS, 0); /* * Fetch the data in RGB format, matching the bitmap context. */ glReadPixels((GLint)0, (GLint)0, (GLint)screenWidth, (GLint)screenHeight, GL_RGB, GL_BYTE, glBitmapData); SwizzleBitmap(); } void wxScreenshotMaker::SwizzleBitmap() { int top, bottom; top = 0; bottom = screenHeight - 1; void * base = glBitmapData; void * topP = NULL; void * bottomP = NULL; while(top < bottom) { topP = (void *)((top * rowSize) + (intptr_t)base); bottomP = (void *)((bottom * rowSize) + (intptr_t)base); bcopy( topP, glRowData, rowSize ); bcopy( bottomP, topP, rowSize ); bcopy( glRowData, bottomP, rowSize ); ++top; --bottom; } } #endif
来源:http://wxwidgets.info/taking-screenshots-with-wxwidgets-under-mac-os-is-really-tricky/
posted on 2011-06-29 15:52 几百人有爱 阅读(412) 评论(0) 编辑 收藏 举报