很久都没写博客了,前段时间ACM那些题都是有空的时候水着玩的,虽然大二的课只有6门,但是作业很多,也一直很忙,刚刚都才完成一个电路设计的实验报告。准备TOEFL,GRE,还要跟着导师做计算机视觉的一些东西,脑细胞死一大片。最近又要用到Windows编程,高中的时候看《Windows程序设计 第五版 珍藏版》学的东西也都忘得差不多了,但是思路还在,只是查MSDN查得很多。既然要处理位图,那得先加载咯。
直接上代码:
1 #include <windows.h> 2 #include <tchar.h> 3 #include "resource.h" 4 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 5 void LoadBMPFile(HWND, HDC, TCHAR *); //加载位图 6 TCHAR * openFileDialog(HWND); //打开文件对话框 7 8 OPENFILENAME ofn; 9 TCHAR szFile[MAX_PATH]; 10 11 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 12 { 13 WNDCLASSEX wcex; //声明窗口类 14 HWND hwnd; 15 MSG msg; 16 TCHAR szWindowClass[] = TEXT("helloworld"); 17 TCHAR szTitle[] = TEXT("My Windows"); 18 19 //窗口类定义 20 wcex.cbSize = sizeof(WNDCLASSEX); 21 wcex.style = CS_HREDRAW | CS_VREDRAW; 22 wcex.lpfnWndProc = WndProc; 23 wcex.cbClsExtra = 0; 24 wcex.cbWndExtra = 0; 25 wcex.hInstance = hInstance; 26 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 27 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 28 wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 29 wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); 30 wcex.lpszClassName = szWindowClass; 31 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); 32 33 //注册窗口类 34 if (!RegisterClassEx(&wcex)) 35 { 36 MessageBox(NULL, TEXT("窗口注册失败"), TEXT("窗口注册"), NULL); 37 return 1; 38 } 39 40 //创建窗口 41 hwnd = CreateWindow( 42 szWindowClass, 43 szTitle, 44 WS_OVERLAPPEDWINDOW, 45 CW_USEDEFAULT, 46 CW_USEDEFAULT, 47 CW_USEDEFAULT, 48 CW_USEDEFAULT, 49 NULL, 50 NULL, 51 hInstance, 52 NULL 53 ); 54 //显示窗口 55 ShowWindow(hwnd, nCmdShow); 56 UpdateWindow(hwnd); 57 58 //消息循环 59 while (GetMessage(&msg, NULL, 0, 0)) 60 { 61 TranslateMessage(&msg); 62 DispatchMessage(&msg); 63 } 64 65 return (int)msg.wParam; 66 } 67 68 //窗口过程 69 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 70 { 71 HDC hdc; 72 PAINTSTRUCT ps; 73 static int count = 0; //用于统计加载次数 74 static TCHAR * path; 75 76 switch (message) 77 { 78 case WM_COMMAND: 79 switch (LOWORD(wParam)) 80 { 81 case ID_FILE_OPEN: //这个地方的处理不太恰当,每次重画都会重新打开一遍位图文件,而不是保存在内存中,等到打开另一张图片再释放。 82 path = openFileDialog(hwnd); 83 hdc = GetDC(hwnd); 84 LoadBMPFile(hwnd, hdc, path); 85 ReleaseDC(hwnd, hdc); 86 count++; 87 break; 88 89 case ID_FILE_EXIT: 90 PostQuitMessage(0); 91 break; 92 } 93 break; 94 case WM_DESTROY: 95 PostQuitMessage(0); 96 break; 97 98 case WM_SIZE: 99 InvalidateRect(hwnd, NULL, TRUE); 100 break; 101 102 case WM_PAINT: 103 hdc = BeginPaint(hwnd, &ps); 104 if(count) 105 LoadBMPFile(hwnd, hdc, path); 106 EndPaint(hwnd, &ps); 107 break; 108 109 default: 110 return DefWindowProc(hwnd, message, wParam, lParam); 111 break; 112 } 113 return 0; 114 } 115 116 void LoadBMPFile(HWND hwnd, HDC hdc, TCHAR * path) 117 { 118 HDC hdcMem; 119 HBITMAP hBmp; //位图句柄 120 BITMAP bmp; 121 RECT clientRect; 122 int x, y; 123 124 hdcMem = CreateCompatibleDC(hdc); //创建一个与指定设备兼容的内存设备上下文环境 125 hBmp = (HBITMAP)LoadImage(NULL, path, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION); 126 GetObject(hBmp, sizeof(BITMAP), &bmp); //得到一个位图图像 127 128 GetClientRect(hwnd, &clientRect); 129 x = (clientRect.left + clientRect.right) / 2 - bmp.bmWidth / 2; 130 y = (clientRect.left + clientRect.bottom) / 2 - bmp.bmHeight / 2; 131 SelectObject(hdcMem, hBmp); 132 BitBlt(hdc, x, y, bmp.bmWidth, bmp.bmHeight, hdcMem, 0, 0, SRCCOPY); 133 //SetStretchBltMode(hdc, HALFTONE); 134 //StretchBlt(hdc, 0, 0, bmp.bmWidth-100, bmp.bmHeight-100, hdcMem, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); 135 DeleteDC(hdcMem); 136 DeleteObject(hBmp); 137 } 138 139 //打开文件对话框 140 TCHAR * openFileDialog(HWND hwnd) 141 { 142 // Initialize OPENFILENAME 143 ZeroMemory(&ofn, sizeof(ofn)); 144 ofn.lStructSize = sizeof(ofn); 145 ofn.hwndOwner = hwnd; 146 ofn.lpstrFile = szFile; 147 ofn.lpstrFile[0] = '\0'; 148 // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 149 // use the contents of szFile to initialize itself. 150 // 151 ofn.nMaxFile = sizeof(szFile); 152 ofn.lpstrFilter = _T("Text files (*.bmp)\0*.bmp\0\0"); 153 ofn.nFilterIndex = 1; 154 ofn.lpstrFileTitle = NULL; 155 ofn.nMaxFileTitle = 0; 156 ofn.lpstrInitialDir = NULL; 157 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 158 ofn.lpstrTitle = _T("打开"); 159 160 GetOpenFileName(&ofn); 161 return (TCHAR*)ofn.lpstrFile; 162 }
因为用到菜单资源,下面是resource.h文件的内容
1 //{{NO_DEPENDENCIES}} 2 // Microsoft Visual C++ generated include file. 3 // Used by LoadBMPFile.rc 4 // 5 #define IDR_MENU1 101 6 #define ID_FILE_OPEN 40001 7 #define ID_FILE_EXIT 40002 8 9 // Next default values for new objects 10 // 11 #ifdef APSTUDIO_INVOKED 12 #ifndef APSTUDIO_READONLY_SYMBOLS 13 #define _APS_NEXT_RESOURCE_VALUE 102 14 #define _APS_NEXT_COMMAND_VALUE 40003 15 #define _APS_NEXT_CONTROL_VALUE 1001 16 #define _APS_NEXT_SYMED_VALUE 101 17 #endif 18 #endif
下面是菜单资源文件内容:
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///// #undef APSTUDIO_READONLY_SYMBOLS ///// // Chinese (Simplified, PRC) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///// // // Menu // IDR_MENU1 MENU BEGIN POPUP "File" BEGIN MENUITEM "Open", ID_FILE_OPEN MENUITEM "Exit", ID_FILE_EXIT END END #endif // Chinese (Simplified, PRC) resources ///// #ifndef APSTUDIO_INVOKED ///// // // Generated from the TEXTINCLUDE 3 resource. // ///// #endif // not APSTUDIO_INVOKED