先前已經能基於GDI顯示png圖像,可是窗口大小和圖像尺寸並不一致。注意到opencv中的imshow的窗口和圖像尺寸一致,這裏進行設置。html
CreateWindow階段並不能肯定窗口大小,可是在窗口處理函數的繪製階段能夠從新調整窗口大小。具體步驟按前後順序:windows
首先讀取圖像(而不是像以前的博客中縮寫的,每次窗口paint時都從新讀取圖像)函數
註冊窗口post
CreateWindowEx
時候隨便設置一個窗口大小ui
case WM_PAINT:
階段判斷一下,若是沒有調整過窗口大小,就調整spa
#include <stdio.h> #include <stdbool.h> #include <windows.h> #include "png.h" #pragma comment(lib, "D:/work/libfc/lib/libpng.lib") #pragma comment(lib, "D:/work/libfc/lib/zlib.lib") //#pragma comment(lib, "msimg32.lib") // for png's alpha channel typedef struct MyWindow { HDC dc; //HGDIOBJ image; HBITMAP hBmp; unsigned char* imdata; int im_width; int im_height; int win_pos_x; // window position, top left point's x coordinate int win_pos_y; // window posttion, top left point's y coordinate bool adjusted; } MyWindow; MyWindow* my_window; enum ImageType {BMP, PNG}; long ReadPngData(const char *szPath, int *pnWidth, int *pnHeight, unsigned char **cbData) { FILE *fp = NULL; long file_size = 0, pos = 0, mPos = 0; int color_type = 0, x = 0, y = 0, block_size = 0; png_infop info_ptr; png_structp png_ptr; png_bytep *row_point = NULL; fp = fopen(szPath, "rb"); if (!fp) return -1; //文件打開錯誤則返回 FILE_ERROR png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); //建立png讀取結構 info_ptr = png_create_info_struct(png_ptr); //png 文件信息結構 png_init_io(png_ptr, fp); //初始化文件 I\O png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); //讀取png文件 *pnWidth = png_get_image_width(png_ptr, info_ptr); //得到圖片寬度 *pnHeight = png_get_image_height(png_ptr, info_ptr); //得到圖片高度 color_type = png_get_color_type(png_ptr, info_ptr); //得到圖片色彩深度 file_size = (*pnWidth) * (*pnHeight) * 4; //計算須要存儲RGB(A)數據所需的內存大小 *cbData = (unsigned char *)malloc(file_size); //申請所需的內容, 並將 *cbData 指向申請的這塊內容 row_point = png_get_rows(png_ptr, info_ptr); //讀取RGB(A)數據 block_size = color_type == 6 ? 4 : 3; //根據是否具備a通道判斷每次所要讀取的數據大小, 具備Alpha通道的每次讀4位, 不然讀3位 //將讀取到的RGB(A)數據按規定格式讀到申請的內存中 for (x = 0; x < *pnHeight; x++) for (y = 0; y < *pnWidth*block_size; y += block_size) { (*cbData)[pos++] = row_point[x][y + 2]; //B (*cbData)[pos++] = row_point[x][y + 1]; //G (*cbData)[pos++] = row_point[x][y + 0]; //R (*cbData)[pos++] = row_point[x][y + 3]; //alpha } png_destroy_read_struct(&png_ptr, &info_ptr, 0); fclose(fp); return file_size; } //int DEFAULT_WIDTH, DEFAULT_HIGHT; void SetWindowSize(HWND hWnd) { if (my_window->adjusted == false) { RECT WindowRect; RECT ClientRect; GetWindowRect(hWnd, &WindowRect); GetClientRect(hWnd, &ClientRect); WindowRect.right += (my_window->im_width - ClientRect.right); WindowRect.bottom += (my_window->im_height - ClientRect.bottom); MoveWindow(hWnd, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, true); } my_window->adjusted = true; } LRESULT __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp) { int image_type = PNG; switch (msg) { case WM_CREATE: if (image_type == BMP) { my_window->hBmp = (HBITMAP)LoadImage(NULL, "D:/work/libfc/imgs/lena512.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); } else if (image_type == PNG) { // my_window->hBmp = CreateBitmap(my_window->im_width, my_window->im_height, 32, 1, my_window->imdata); } if (my_window->hBmp == NULL) MessageBox(window, "Could not load image!", "Error", MB_OK | MB_ICONEXCLAMATION); break; case WM_PAINT: { SetWindowSize(window); BITMAP bm; PAINTSTRUCT ps; HDC hdc = BeginPaint(window, &ps); SetStretchBltMode(hdc, COLORONCOLOR); my_window->dc = CreateCompatibleDC(hdc); HBITMAP hbmOld = SelectObject(my_window->dc, my_window->hBmp); GetObject(my_window->hBmp, sizeof(bm), &bm); #if 1 //原樣拷貝,不支持拉伸 BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, my_window->dc, 0, 0, SRCCOPY); //AlphaBlend(hdc, 100, 0, bm.bmWidth, bm.bmHeight, my_window->dc, 0, 0, bm.bmWidth, bm.bmHeight, bf); #else RECT rcClient; GetClientRect(window, &rcClient);//得到客戶區的大小 int nWidth = rcClient.right - rcClient.left;//客戶區的寬度 int nHeight = rcClient.bottom - rcClient.top;//客戶區的高度 StretchBlt(hdc, 0, 0, nWidth, nHeight, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);//拉伸拷貝 #endif SelectObject(my_window->dc, hbmOld); DeleteDC(my_window->dc); EndPaint(window, &ps); } break; case WM_DESTROY: printf("\ndestroying window\n"); PostQuitMessage(0); return 0L; case WM_LBUTTONDOWN: printf("\nmouse left button down at (%d, %d)\n", LOWORD(lp), HIWORD(lp)); // fall thru default: //printf("."); return DefWindowProc(window, msg, wp, lp); } } const char* szWindowClass = "myclass"; ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); /* Win 3.x */ wc.style = CS_DBLCLKS; wc.lpfnWndProc = WindowProcedure; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = GetModuleHandle(0); wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wc.lpszMenuName = 0; wc.lpszClassName = szWindowClass; /* Win 4.0 */ wc.hIconSm = LoadIcon(0, IDI_APPLICATION); return RegisterClassEx(&wc); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { my_window->win_pos_x = 600; my_window->win_pos_y = 300; DWORD defStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU; HWND hwnd = CreateWindowEx(0, szWindowClass, "title", defStyle, my_window->win_pos_x, my_window->win_pos_y, my_window->im_width, my_window->im_height, 0, 0, hInstance, 0); if (!hwnd) { return FALSE; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); return TRUE; } void create_my_window(MyWindow** _my_window) { MyWindow* my_window = (MyWindow*)malloc(sizeof(MyWindow)); my_window->dc = NULL; my_window->imdata = NULL; my_window->hBmp = NULL; my_window->adjusted = false; *_my_window = my_window; // write back } void destroy_my_window(MyWindow* my_window) { if (my_window) { free(my_window); } } int main() { printf("hello world!\n"); create_my_window(&my_window); int im_width, im_height; unsigned char* imdata; ReadPngData("D:/work/libfc/imgs/op.png", &im_width, &im_height, &imdata); my_window->im_width = im_width; my_window->im_height = im_height; my_window->imdata = imdata; HINSTANCE hInstance = GetModuleHandle(0); int nCmdShow = SW_SHOWDEFAULT; MyRegisterClass(hInstance); if (!InitInstance(hInstance, nCmdShow)) { return FALSE; } MSG msg; while (GetMessage(&msg, 0, 0, 0)) { DispatchMessage(&msg); } destroy_my_window(my_window); free(imdata); return 0; }
設置窗口客戶區大小的一種辦法.net