掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
[初心者] メモリーアクセス違反で困っています (ID:71961)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
お世話になります。 環境:WinXP SP2, VS2005 Express C++入門したばかりの初心者です。 いろいろサンプルに触れながら基礎講座で勉強しています。 やりたいこと: ウィンドウのスクリーンショットをJPEG保存したいです。 ググってみたら以下のようなサンプルがありました。(長くて申し訳ありません。) ---------------------------------------- /* BITMAP-DIB変換とウインドウのBMP保存 2000/ 4/22 - 2001/ 4/10 宍戸 輝光 */ #include <windows.h> #include <stdlib.h> #include <time.h> HWND hwMain; HINSTANCE hInst; LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); void saveBMP(HWND,LPCTSTR); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, PSTR szCmdLine,int iCmdShow){ MSG msg; WNDCLASSEX wndclass; hInst=hInstance; /* プロセスのハンドルを保存 */ srand((unsigned)time(NULL)); 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(NULL,IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "CWindow"; wndclass.hIconSm = LoadIcon(NULL,IDI_APPLICATION); RegisterClassEx(&wndclass); /* ウインドウクラス登録 */ hwMain = CreateWindow("CWindow","BITMAP-DIB変換", WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,256,96, NULL,NULL,hInstance,NULL); ShowWindow(hwMain,iCmdShow); /* ウインドウを表示 */ UpdateWindow(hwMain); while (GetMessage(&msg,NULL,0,0)) { /* メッセージループ */ TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { int i,x,y,r,g,b; RECT rec; HDC hdc; PAINTSTRUCT ps; HWND btSave; switch (iMsg) { case WM_CREATE: /* ウインドウ作成時の処理 */ /* ボタン作成 */ btSave=CreateWindow("Button","保存",WS_CHILD|WS_VISIBLE, 8,8,80,32,hwnd,(HMENU)0,hInst,NULL); return 0; case WM_COMMAND: /* コマンドメッセージ */ switch (LOWORD(wParam)) { case 0: /* 保存ボタン */ saveBMP(hwnd,"test.bmp"); break; } return 0; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); GetClientRect(hwnd,&rec); /* クライアント領域取得 */ for (i=0;i<(rec.right*rec.bottom)/48;i++) { x=(int)(((double)rand()/(double)RAND_MAX)*rec.right); y=(int)(((double)rand()/(double)RAND_MAX)*rec.bottom); r=(int)(((double)rand()/(double)RAND_MAX)*160)+96; g=(int)(((double)rand()/(double)RAND_MAX)*128)+128; b=(int)(((double)rand()/(double)RAND_MAX)*192)+64; SetPixel(hdc,x,y,RGB(r,g,b)); } EndPaint(hwnd,&ps); return 0; case WM_DESTROY : /* 終了処理 */ PostQuitMessage(0); return 0; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; } void saveBMP(HWND hwnd,LPCTSTR lpszFn) { DWORD dwSize,dwFSize,dwWidth,dwHeight,dwLength; HANDLE fh; LPBITMAPFILEHEADER lpHead; LPBITMAPINFOHEADER lpInfo; LPBYTE lpBuf,lpPixel; RECT rec; HDC hdc,hdcMem; HBITMAP hBMP,hOld; GetClientRect(hwnd,&rec); /* クライアント領域取得 */ dwWidth=rec.right; dwHeight=rec.bottom; if ((dwWidth*3) % 4==0) /* バッファの1ラインの長さを計算 */ dwLength=dwWidth*3; else dwLength=dwWidth*3+(4-(dwWidth*3) % 4); /* 書き込み用バッファのサイズ計算 */ dwFSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+dwLength*dwHeight; /* バッファ確保とポインタ設定 */ lpBuf=(LPBYTE)GlobalAlloc(GPTR,dwFSize); lpHead=(LPBITMAPFILEHEADER)lpBuf; lpInfo=(LPBITMAPINFOHEADER)(lpBuf+sizeof(BITMAPFILEHEADER)); lpPixel=lpBuf+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); /* 24ビットBMPファイルのヘッダ作成 */ lpHead->bfType='M'*256+'B'; lpHead->bfSize=dwFSize; lpHead->bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); lpInfo->biSize=sizeof(BITMAPINFOHEADER); lpInfo->biWidth=dwWidth; lpInfo->biHeight=dwHeight; lpInfo->biPlanes=1; lpInfo->biBitCount=24; /* ウインドウのデバイスコンテキスト取得 */ hdc=GetDC(hwnd); /* ウインドウのデバイスコンテキスト互換のBITMAP作成 */ hBMP=CreateCompatibleBitmap(hdc,dwWidth,dwHeight); /* BITMAPにウインドウのクライアント領域をコピー */ hdcMem=CreateCompatibleDC(hdc); hOld=SelectObject(hdcMem,hBMP); BitBlt(hdcMem,0,0,dwWidth,dwHeight,hdc,0,0,SRCCOPY); SelectObject(hdcMem,hOld); GetDIBits(hdc,hBMP,0,dwHeight,lpPixel,(LPBITMAPINFO)lpInfo,DIB_RGB_COLORS); ReleaseDC(hwnd,hdc); DeleteObject(hBMP); DeleteObject(hdcMem); /* バッファをファイルに書き出す */ fh=CreateFile(lpszFn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); WriteFile(fh,lpBuf,dwFSize,&dwSize,NULL); CloseHandle(fh); GlobalFree(lpBuf); } ---------------------------------------- これはBMP保存だったのでJPEG保存する方法をまたググって 以下のサンプルが見つかりました。 ATLが使えないのでGDI+で… ---------------------------------------- int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0; // number of image encoders UINT size = 0; // size of the image encoder array in bytes ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if(size == 0) return -1; // Failure pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if(pImageCodecInfo == NULL) return -1; // Failure GetImageEncoders(num, size, pImageCodecInfo); for(UINT j = 0; j < num; ++j) { if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; // Success } } free(pImageCodecInfo); return -1; // Failure } ... ULONG dwToken; Gdiplus::GdiplusStartupInput input; Gdiplus::GdiplusStartupOutput output; Gdiplus::Status status = Gdiplus::GdiplusStartup(&dwToken, &input, &output); if(status == Gdiplus::Ok) { CLSID jpgClsid; CLSID bmpClsid; GetEncoderClsid(L"image/jpeg", &jpgClsid); Gdiplus::Bitmap SrcBitmap(L"c:\\test.bmp", FALSE); SrcBitmap.Save(L"c:\\test.jpg", &bmpClsid); Gdiplus::GdiplusShutdown(dwToken); } ... ---------------------------------------- そのままJPEGに保存するように修正するのはまだ無理だと思って 上記のBMPでキャプチャするコードに挿入してみました。 ---------------------------------------- /* BITMAP-DIB変換とウインドウのBMP保存 2000/ 4/22 - 2001/ 4/10 宍戸 輝光 */ #include "stdafx.h" #include <time.h> using namespace Gdiplus; HWND hwMain; HINSTANCE hInst; LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); void saveBMP(HWND,LPCTSTR); int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) { UINT num = 0; // number of image encoders UINT size = 0; // size of the image encoder array in bytes ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&num, &size); if(size == 0) return -1; // Failure pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); if(pImageCodecInfo == NULL) return -1; // Failure GetImageEncoders(num, size, pImageCodecInfo); for(UINT j = 0; j < num; ++j) { if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) { *pClsid = pImageCodecInfo[j].Clsid; free(pImageCodecInfo); return j; // Success } } free(pImageCodecInfo); return -1; // Failure } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, PSTR szCmdLine,int iCmdShow){ …… ReleaseDC(hwnd,hdc); DeleteObject(hBMP); DeleteObject(hdcMem); /* バッファをファイルに書き出す */ fh=CreateFile(lpszFn,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); WriteFile(fh,lpBuf,dwFSize,&dwSize,NULL); CloseHandle(fh); GlobalFree(lpBuf); //**************test ULONG dwToken; GdiplusStartupInput input; GdiplusStartupOutput output; Status status = GdiplusStartup(&dwToken, &input, &output); if(status == Ok) { CLSID jpgClsid; CLSID bmpClsid; GetEncoderClsid(L"image/jpeg", &jpgClsid); Bitmap SrcBitmap(L"test.bmp", FALSE); SrcBitmap.Save(L"test.jpg", &bmpClsid); GdiplusShutdown(dwToken); } //**************test } ---------------------------------------- ……の所は一緒です。 これをデバッグしたら、保存ボタンを押したとき、以下のエラーが発生します。 ---------------------------------------- test4.exe の 0x4af171cf で初回の例外が発生しました: 0xC0000005: 場所 0x00d940a4 を読み込み中にアクセス違反が発生しました。 test4.exe の 0x4af171cf でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00d940a4 を読み込み中にアクセス違反が発生しました。 ---------------------------------------- 場所はここです。 ===========(GdiplusBitmap.h)============ inline Image::~Image() { DllExports::GdipDisposeImage(nativeImage); } //<-ここです。 ---------------------------------------- ポインター等まだちゃんと把握できていないまま 質問させていただき申し訳ありませんが ご指導よろしくお願いします。
←解決時は質問者本人がここをチェックしてください。
更新する
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.