admin管理员组

文章数量:1621117

用Matlab载入一张图,再显示,好像非常非常容易…

C语言就完全不一样了。很复杂。

原因很简单,因为Matlab都封装好了嘛,而C语言要把所有的细节都体现出来。

以下代码,也来自网络。注意里面很多的注释……


总之,

1. 首先要获得DC(Device Context),设备环境、设备描述表。差不多描述的就是应用程序的客户区。

通过它,Windows操作系统知道我们希望怎么与设备(显示器)打交道,

操作系统再通过驱动去驱动物理设备和驱动,也许是改变电压电流等等,

让屏幕上做出一些相应的动作,比如显示一张图。

2. 显示的东西,首先要载入内存,不然系统怎么知道要显示的是什么呢?

而内存里的东西,要和屏幕上显示的东西,兼容,所以要在内存里创建一个兼容的DC。

为了显示出某张图,(1)要载入图片,比如,从硬盘上载入一张BMP图片到内存。

(2)把内存中的图片数据(肯定是一堆0101了…),拷贝到在内存中虚拟出的一个虚拟DC(通过CreateCompatibleDC函数),

该虚拟DC兼容真正的DC(在paint消息里,用BeginPaint函数得到)。

(3)通过一个“贴图”的函数(BitBlt),把内存中虚拟出来DC里的图像数据(就是我们希望显示的那幅图),显示到屏幕上。

3. 在步骤2(3)中,为了让屏幕显示,还必须要由操作系统帮助我们显示,于是要通过DC(和驱动,但驱动我们看不见了),

把图片显示出来。

/*----------------------------------------
BRICKS1.C -- LoadBitmap Demonstration
(c) Charles Petzold, 1998
----------------------------------------*/

#include 
  
  
   
   
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName [] = TEXT ("Bricks1") ;
	HWND         hwnd ;
	MSG          msg ;
	WNDCLASS     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 (WHITE_BRUSH) ;
	wndclass.lpszMenuName  = NULL ;
	wndclass.lpszClassName = szAppName ;
	
	if (!RegisterClass (&wndclass))
	{
		MessageBox (NULL, TEXT ("This program requires Windows NT!"),
			szAppName, MB_ICONERROR) ;
		return 0 ;
	}
	
	hwnd = CreateWindow (szAppName, TEXT ("LoadBitmap Demo"), 
		WS_OVERLAPPEDWINDOW, 
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL) ;
	
	ShowWindow (hwnd, iCmdShow) ;
	UpdateWindow (hwnd) ;
	
	while (GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg) ;
		DispatchMessage (&msg) ;
	}
	return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HBITMAP hBitmap ;
	static int     cxClient, cyClient, cxSource, cySource ;
	BITMAP         bitmap ;
	HDC            hdc, hdcMem ;
	HINSTANCE      hInstance ;
	int            x, y ;
	PAINTSTRUCT    ps ;
	
	switch (message)
	{
	case WM_CREATE:
		hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
		
		// 注意,MAKEINTRESOURCE (IDM_BITMAP)。IDM_BITMAP是图片资源文件的ID。
		hBitmap = LoadBitmap (hInstance, MAKEINTRESOURCE (IDM_BITMAP)/*TEXT("Bricks")*/) ;
		
		GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;
		
		cxSource = bitmap.bmWidth ;
		cySource = bitmap.bmHeight ;
		
		return 0 ;
		
	case WM_SIZE: // size消息一来,paint就来。有无效区了。
		cxClient = LOWORD (lParam) ;
		cyClient = HIWORD (lParam) ;
		return 0 ;
		
	case WM_PAINT:

		// 在WM_PAINT消息下,只能用这样的方式拿
		// 而BeginPaint也只能在WM_PAINT消息下用
		// EndPaint也只能在WM_PAINT消息下用

		// 要想画图,必须拿到hdc
		// 写字也是画图!

		// ps这个数据结构里的rc那个rect 就是无效区
		// 【警告】 一定要释放资源!
		hdc = BeginPaint (hwnd, &ps) ; // 用这个来拿,后面一定要释放资源!!!
		// BeginPaint会自动使无效区有效。

		// 【警告】
		//  好习惯:一定写好3行!
		// begin,end, return 0;

		// 要让内存里的数据刚好能贴到屏幕上, --> 要兼容
		hdcMem = CreateCompatibleDC (hdc) ; // 在内存里面虚拟一个HDC出来,与hdc兼容
		// 后面也一定要释放资源! DeleteDC (hdcMem) ;
	
		// 把图贴到虚设备上了。
		SelectObject (hdcMem, hBitmap) ; // 相当于:把bitmap的内容,放到hdcMem内存里虚拟出来的设备一样了

		// 尽管for了一个大区域,但是只刷无效区 -_-!
		for (y = 100 ; y < cyClient - 100 ; y += cySource)
		{
			for (x = 100 ; x < cxClient - 100 ; x += cxSource)
			{
				// hdc 代表了 显示器上,属于程序的客户区
				// hdcMem 代表了 内存里的一张图
				BitBlt (hdc, x, y, cxSource, cySource, hdcMem, 0, 0, SRCCOPY) ; // 贴图的函数!
				 Sleep(10);
			}
		}
			
		DeleteDC (hdcMem) ;
		EndPaint (hwnd, &ps) ; // 一定要释放资源!
		return 0 ;

		// 【非常不推荐】按鼠标,直接去做和paint解决 -_-! 比如,直接用InvalidateRect。
		// 应该根据鼠标位置,发送某个自定义消息吧 -_-!
		// 最大最小化以后,应该还用一个数据结构把点开的砖记下吧 -_-!
		// paint消息怎么处理???
		// 画图。。。不一定是要用paint!!
		// paint是在paint消息下面用。
		// 其他消息,直接画,直接贴就好了 -_-!

	case WM_LBUTTONDOWN:
		
		// 不是 要先清空,再贴图
		// 显示器 ... 直接贴就是了! 只有一层…
		// 覆盖就好了!赋值嘛。。。

		// 第三个参数若是false,背景不会重绘。就本程序而言,也不会重绘了
		InvalidateRect(hwnd, NULL, TRUE/*TRUE*/);
		
		/************************************************************************/
		/* 
		The InvalidateRect function adds a rectangle to the specified window's update region. The update region represents the portion of the window's client area that must be redrawn. 
		
		  BOOL InvalidateRect(
		  HWND hWnd,  // handle of window with changed update region
		  CONST RECT *lpRect,
		  // address of rectangle coordinates
		  BOOL bErase // erase-background flag
		  );
		  
			Parameters
			hWnd 
			Handle to the window whose update region has changed. If this parameter is NULL, the system invalidates and redraws all windows, and sends theWM_ERASEBKGND and WM_NCPAINT messages to the window procedure before the function returns. 
			lpRect 
			Pointer to a RECT structure that contains the client coordinates of the rectangle to be added to the update region. If this parameter is NULL, the entire client area is added to the update region. 
			bErase 
			Specifies whether the background within the update region is to be erased when the update region is processed. If this parameter is TRUE, the background is erased when the BeginPaint function is called. If this parameter is FALSE, the background remains unchanged. 

		*/
		/************************************************************************/

		return 0 ;
			
	case WM_DESTROY:
		DeleteObject (hBitmap) ;
		PostQuitMessage (0) ;
		return 0 ;
	}
	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

  
  



上面是用一个for循环,贴了一堆。
如果只需要贴一张图,还要求这张图在客户区中央显示,可以利用size消息,来获取客户区的大小。 最后,利用客户区的大小和图片大小,算出图片的起点坐标。 代码如下。显示的是一辈子也买不起的Ferrari FF的照片了…
/*----------------------------------------
BRICKS1.C -- LoadBitmap Demonstration
(c) Charles Petzold, 1998
----------------------------------------*/

#include 
    
    
     
     
#include "resource.h"

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName [] = TEXT ("Bricks1") ;
	HWND         hwnd ;
	MSG          msg ;
	WNDCLASS     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 (WHITE_BRUSH) ;
	wndclass.lpszMenuName  = NULL ;
	wndclass.lpszClassName = szAppName ;
	
	if (!RegisterClass (&wndclass))
	{
		MessageBox (NULL, TEXT ("This program requires Windows NT!"),
			szAppName, MB_ICONERROR) ;
		return 0 ;
	}
	
	hwnd = CreateWindow (szAppName, TEXT ("LoadBitmap Demo"), 
		WS_OVERLAPPEDWINDOW, 
		CW_USEDEFAULT, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL) ;
	
	ShowWindow (hwnd, iCmdShow) ;
	UpdateWindow (hwnd) ;
	
	while (GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg) ;
		DispatchMessage (&msg) ;
	}
	return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HBITMAP hBitmap ;
	static int     cxClient, cyClient, cxSource, cySource ;
	BITMAP         bitmap ;
	HDC            hdc, hdcMem ;
	HINSTANCE      hInstance ;
	int            x = 0, y = 100 ;
	PAINTSTRUCT    ps ;
	
	switch (message)
	{
	case WM_CREATE:
		hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
		
		hBitmap = LoadBitmap (hInstance, MAKEINTRESOURCE (IDB_FF)) ;
		
		GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;
		
		cxSource = bitmap.bmWidth ;
		cySource = bitmap.bmHeight ;
		
		return 0 ;
		
	case WM_SIZE:
		cxClient = LOWORD (lParam) ;
		cyClient = HIWORD (lParam) ;
		return 0 ;
		
	case WM_PAINT:
		hdc = BeginPaint (hwnd, &ps) ;

		// 为了让贴图的位置在客户区的正中
		// 水平、垂直居中显示
		x = cxClient / 2 - cxSource/2;
		y = cyClient / 2 - cySource/2;
		
		hdcMem = CreateCompatibleDC (hdc) ;
		SelectObject (hdcMem, hBitmap) ;
		
		BitBlt (hdc, x, y, cxSource, cySource, hdcMem, 0, 0, SRCCOPY) ;
		
		DeleteDC (hdcMem) ;
		EndPaint (hwnd, &ps) ;
		return 0 ;
		
	case WM_DESTROY:
		DeleteObject (hBitmap) ;
		PostQuitMessage (0) ;
		return 0 ;
	}
	return DefWindowProc (hwnd, message, wParam, lParam) ;
}

    
    



本文标签: 一幅程序设计图像Windows