文档章节

基于CButton编写的图片控件

moki_oschina
 moki_oschina
发布于 2017/05/17 11:35
字数 3003
阅读 10
收藏 0
点赞 0
评论 0

头文件:ButtonPicture.h

#pragma once
#include <atlimage.h>
#include <string>
using namespace ATL;

struct IMAGEPARAMENT {          
	int     nWidth;   
	int     nHeight;   
	int     nBitCount;   
	int     nBytesPerLine;   
	int     nBytesPerPixel;   
	int     nNumColors;   
	int     nSize;   
};   
class CButtonPic : public CButton
{
public:
	CButtonPic();
	virtual ~CButtonPic();
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:	
	DECLARE_MESSAGE_MAP()
	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);

public:
	void ShowImage(std::string strimgpath,HWND parent_wnd);
	void OnSelectStampPos();
	void OnRorateUp90();
	void OnRorateUp180();
	void OnRorateDown90();
	void OnRorateDown180();
	void OnBlownUp();
	void OnBlownDown();
	void OnRightSize();
private:
	void DrawImage(void);
	void GetRightImageSize(double &imgscale,int &right_width,int &right_height);
	bool CreateBitMap(CBitmap &mBitmap);
	void ResetScrollInfo(void);
	void RorateImage(CImage &in_image,CImage &out_image,double angle);
	bool ResizeImage(CImage &image,int destWidth, int destHeight,CImage &newimg);
	bool ImageCopy(CImage &srcImage, CImage &destImage);

private:
	HWND m_parent_wnd;
	std::string m_imgpath;
	CImage m_img;
	double m_imgscale;
	int m_angle;
	double m_rightscale;
	int m_right_width;
	int m_right_height;
	int m_scale_idx;

	//滚动条
	int m_scrollmaxsize_h;
	int m_scrollpos_h;
	int m_scrollpagesize_h;
	int m_scrollmaxsize_w;
	int m_scrollpos_w;
	int m_scrollpagesize_w;
	int m_onestep;
	//
	bool selstampflag;
	POINT m_stamppoint;
	POINT m_realstamppoint;
	int m_stamp_r;
public:
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};

源文件:ButtonPicture.cpp

#include "stdafx.h"
#include "ButtonPicture.h"
#include "CIProcess.h"
#include <sstream>
#include <iostream>
#if 0
#include<opencv2/imgproc/imgproc.hpp>  
#include<opencv2/highgui/highgui.hpp> 
#include <cv.h>
#endif
#include <math.h>

//using namespace cv; 
using namespace std;

const double g_scale_arr[9] = {1.0,1.1,1.2,1.5,1.8,2.0,3.0,4.0,5.0};

CButtonPic::CButtonPic()
{	
	m_parent_wnd = NULL;
	m_imgpath = "";
	m_imgscale = 1.0;
	m_angle = 0;

	m_rightscale = 1.0;
	m_right_width = 0;
	m_right_height = 0;
	m_scale_idx = 0;

	m_scrollmaxsize_h = 0;
	m_scrollpos_h = 0;
	m_scrollpagesize_h = 0;
	m_scrollmaxsize_w = 0;
	m_scrollpos_w = 0;
	m_scrollpagesize_w = 0;
	m_onestep = 0;

	selstampflag = false;
	m_stamppoint.x = 0;
	m_stamppoint.y = 0;
	m_realstamppoint.x = 0;
	m_realstamppoint.y = 0;
	m_stamp_r = 40;
}

CButtonPic::~CButtonPic()
{
}

BEGIN_MESSAGE_MAP(CButtonPic, CButton)	
	ON_WM_DRAWITEM()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

void CButtonPic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	// TODO: Add your code to draw the specified item
	//设置背景色
	CDC* pDC = this->GetDC();
	CRect rc;
	this->GetClientRect(&rc);
	FillRect(this->GetDC()->GetSafeHdc(),&rc,CBrush(RGB(99,99,99)));
	if (m_imgpath.empty())
	{
		return;
	}
	//作图
	DrawImage();
}
void CButtonPic::DrawImage(void)
{
	//	
	CDC* pDC = this->GetDC();
	CRect rc;
	this->GetClientRect(&rc);
	CBitmap cbmp;
	BITMAP bm;
	CreateBitMap(cbmp);
	cbmp.GetBitmap(&bm);
	CDC dcImage;

	dcImage.CreateCompatibleDC(pDC); 
	dcImage.SelectObject(&cbmp);

	//画图
	int cx = (rc.Width() - bm.bmWidth)/2>0?(rc.Width() - bm.bmWidth)/2:0;
	int	cy = (rc.Height() - bm.bmHeight)/2>0?(rc.Height() - bm.bmHeight)/2:0; 
	pDC->StretchBlt(cx,cy,rc.Width(),rc.Height(), &dcImage,m_scrollpos_w ,m_scrollpos_h,rc.Width(),rc.Height(),SRCCOPY);
	DeleteObject(cbmp);
	DeleteDC(dcImage);
}
bool CButtonPic::CreateBitMap(CBitmap &mBitmap)
{
	//转换成位图
	CDC *pDC = GetDC();
	CDC memDC;	

	memDC.CreateCompatibleDC(pDC);
	mBitmap.CreateCompatibleBitmap(pDC,m_img.GetWidth(),m_img.GetHeight());
	CBitmap *OldBitmap =memDC.SelectObject(&mBitmap);
	m_img.Draw(memDC.m_hDC,0,0);
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{		
		CPen  pen;
		pen.CreatePen(PS_INSIDEFRAME,2,RGB(255,0,0));	
		CPen  *oldpen=memDC.SelectObject(&pen); 
		CBrush brs;  
		brs.CreateHatchBrush(HS_CROSS,RGB(255,0,0));
		CBrush *pOldBrush = memDC.SelectObject(&brs);
		//画圆心
		memDC.Ellipse(m_stamppoint.x-2,m_stamppoint.y-2,m_stamppoint.x+2,m_stamppoint.y+2);
		//画圆圈
		memDC.SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)));
		memDC.Ellipse(m_stamppoint.x-m_stamp_r,m_stamppoint.y-m_stamp_r,m_stamppoint.x+m_stamp_r,m_stamppoint.y+m_stamp_r);
		memDC.SelectObject(pOldBrush);
		memDC.SelectObject(oldpen);
		brs.DeleteObject(); 
		pen.DeleteObject();
	}
	memDC.SelectObject(OldBitmap);
	DeleteDC(memDC);	
	OldBitmap = NULL;

	return true;
}
void CButtonPic::ResetScrollInfo(void)
{
	LPSCROLLINFO  lpsi = NULL;
	lpsi = new SCROLLINFO;
	CRect rc;
	this->GetClientRect(&rc);

	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();

	m_scrollmaxsize_w = img_width;
	m_scrollmaxsize_h = img_height;
	m_scrollpagesize_w = rc.Width();
	m_scrollpagesize_h = rc.Height();
	m_onestep = 10;
	m_scrollpos_w = 0;
	m_scrollpos_h = 0;

	this->SetScrollRange( SB_HORZ,0,m_scrollmaxsize_w);
	this->SetScrollRange( SB_VERT,0,m_scrollmaxsize_h);
	this->GetScrollInfo(SB_HORZ,lpsi);
	lpsi->nPage = m_scrollpagesize_w;
	this->SetScrollInfo(SB_HORZ,lpsi);
	this->GetScrollInfo(SB_VERT,lpsi);
	lpsi->nPage = m_scrollpagesize_h;
	this->SetScrollInfo(SB_VERT,lpsi);
	if (lpsi!=NULL)
	{
		delete lpsi;
		lpsi = NULL;
	}
}
bool CButtonPic::ImageCopy(CImage &srcImage, CImage &destImage)  
{  
	int i,j;//循环变量  
	if(srcImage.IsNull())  
		return FALSE;  
	//源图像参数  
	BYTE* srcPtr=(BYTE*)srcImage.GetBits();  
	int srcBitsCount=srcImage.GetBPP();  
	int srcWidth=srcImage.GetWidth();  
	int srcHeight=srcImage.GetHeight();  
	int srcPitch=srcImage.GetPitch();   
	//销毁原有图像  
	if( !destImage.IsNull())  
	{  
		destImage.Destroy();  
	}  
	//创建新图像  
	if(srcBitsCount==32)   //支持alpha通道  
	{  
		destImage.Create(srcWidth,srcHeight,srcBitsCount,1);  
	}  
	else  
	{  
		destImage.Create(srcWidth,srcHeight,srcBitsCount,0);  
	}  
	//加载调色板  
	if(srcBitsCount<=8&&srcImage.IsIndexed())//需要调色板  
	{  
		RGBQUAD pal[256];  
		int nColors=srcImage.GetMaxColorTableEntries();  
		if(nColors>0)  
		{       
			srcImage.GetColorTable(0,nColors,pal);  
			destImage.SetColorTable(0,nColors,pal);//复制调色板程序  
		}     
	}   
	//目标图像参数  
	BYTE *destPtr=(BYTE*)destImage.GetBits();  
	int destPitch=destImage.GetPitch();  
	//复制图像数据  
	for(i=0 ; i<srcHeight;i++)  
	{  
		memcpy( destPtr+i*destPitch, srcPtr+i*srcPitch, abs(srcPitch) );  
	}   

	return TRUE;  
} 
void CButtonPic::RorateImage(CImage &in_image,CImage &out_image,double angle)
{
#if 0
	in_image.Save("src.jpg");
	IplImage *in_src_img = NULL;  
	IplImage *out_dest_img = NULL;  

	in_src_img = cvLoadImage("src.jpg",CV_LOAD_IMAGE_COLOR);  
	if (in_src_img == NULL)
	{
		return ;
	}
	double tmpangle = angle * CV_PI / 180.;
	double a = sin(tmpangle), b = cos(tmpangle);
	int width = in_src_img->width;  
	int height = in_src_img->height;  
	int width_rotate= int(height * fabs(a) + width * fabs(b));  
	int height_rotate=int(width * fabs(a) + height * fabs(b));
	float map[6];
	CvMat map_matrix = cvMat(2, 3, CV_32F, map);
	CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2);  
	cv2DRotationMatrix(center, angle, 1.0, &map_matrix);  
	map[2] += (width_rotate - width) / 2;  
	map[5] += (height_rotate - height) / 2; 
	out_dest_img = cvCreateImage(cvSize(width_rotate, height_rotate), in_src_img->depth, in_src_img->nChannels); 
	cvWarpAffine( in_src_img,out_dest_img, &map_matrix, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(0));  
	cvSaveImage("rorate.jpg",out_dest_img);
	if (in_src_img)
	{
		cvReleaseImage(&in_src_img);
		in_src_img = NULL;
	}
	if (out_dest_img)
	{
		cvReleaseImage(&out_dest_img);
		out_dest_img = NULL;
	}
	out_image.Load("rorate.jpg");
#endif
}
void CButtonPic::GetRightImageSize(double &imgscale,int &right_width,int &right_height)
{
	CImage src_img;	
	ImageCopy(m_img,src_img);
	if (src_img.IsNull())
	{
		return;
	}	
	
	CRect rc;
	this->GetClientRect(&rc);
	int wnd_width = rc.Width();
	int wnd_height = rc.Height();
	int src_img_width = src_img.GetWidth();
	int src_img_height = src_img.GetHeight();
	if ((src_img_width * wnd_height) > (src_img_height * wnd_width))
		{
			right_width = wnd_width;
			right_height = (wnd_width * src_img_height) / src_img_width;
			imgscale = src_img_width * 1.0 / wnd_width;
		}
		else
		{
			right_height = wnd_height;
			right_width = (src_img_width * wnd_height) / src_img_height;
			imgscale = src_img_height * 1.0 / wnd_height;
		}
	ResizeImage(src_img,right_width,right_height,m_img);
	src_img.Destroy();
}
void CButtonPic::ShowImage(std::string strimgpath,HWND parent_wnd)
{
	m_parent_wnd = parent_wnd;
	m_imgpath = strimgpath;
	CString imgpath = m_imgpath.c_str();
	if (!m_img.IsNull())
	{
		m_img.Destroy();
	}
	m_img.Load(imgpath);
	if (m_img.IsNull())
	{
		return;
	}	
	GetRightImageSize(m_rightscale,m_right_width,m_right_height);	
	m_scale_idx = 0;
	m_imgscale = m_rightscale;	
	m_stamppoint.x = 0;
	m_stamppoint.y = 0;
	
	ResetScrollInfo();
	Invalidate();
}

void CButtonPic::OnSelectStampPos()
{
	// TODO: 在此添加命令处理程序代码
	selstampflag = true;
}


void CButtonPic::OnRorateUp90()
{
	// TODO: 在此添加命令处理程序代码
	m_angle = m_angle + 90;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,270);
	CIProcess::RotateCimage(&m_img,&rorate_img,270);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印点
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		int i_val = m_stamppoint.x;
		m_stamppoint.x = m_stamppoint.y;
		m_stamppoint.y = m_img.GetHeight() - i_val;
	}
	ResetScrollInfo();
	Invalidate();
}


void CButtonPic::OnRorateUp180()
{
	// TODO: 在此添加命令处理程序代码
	m_angle = m_angle + 180;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,180);
	CIProcess::RotateCimage(&m_img,&rorate_img,180);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印点
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		m_stamppoint.x = m_img.GetWidth() - m_stamppoint.x;
		m_stamppoint.y = m_img.GetHeight() - m_stamppoint.y;
	}
	ResetScrollInfo();
	Invalidate();
}


void CButtonPic::OnRorateDown90()
{
	// TODO: 在此添加命令处理程序代码
	m_angle = m_angle + 270;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,90);
	CIProcess::RotateCimage(&m_img,&rorate_img,90);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印点
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		int i_val = m_stamppoint.y;
		m_stamppoint.y = m_stamppoint.x;		
		m_stamppoint.x = m_img.GetWidth() - i_val;
	}
	ResetScrollInfo();
	Invalidate();
}


void CButtonPic::OnRorateDown180()
{
	// TODO: 在此添加命令处理程序代码
	m_angle = m_angle + 180;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,180);
	CIProcess::RotateCimage(&m_img,&rorate_img,180);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印点
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		m_stamppoint.x = m_img.GetWidth() - m_stamppoint.x;
		m_stamppoint.y = m_img.GetHeight() - m_stamppoint.y;
	}
	ResetScrollInfo();
	Invalidate();
}

bool CButtonPic::ResizeImage(CImage &image,int destWidth, int destHeight,CImage &newimg)
{
	//销毁原有图像  
	if( !newimg.IsNull())  
	{  
		newimg.Destroy();  
	}  
	if(!newimg.CreateEx(destWidth, destHeight, 24, BI_RGB))
	{
		return false;
	}
	int nPreMode = ::SetStretchBltMode(newimg.GetDC(),  HALFTONE);
	newimg.ReleaseDC();
	image.Draw(newimg.GetDC(), 0, 0, destWidth, destHeight, 0, 0, image.GetWidth(), image.GetHeight());
	newimg.ReleaseDC();
	::SetBrushOrgEx(newimg.GetDC(), 0, 0, NULL); 
	newimg.ReleaseDC();
	::SetStretchBltMode(newimg.GetDC(), nPreMode);
	newimg.ReleaseDC();	
	return true;
}
void CButtonPic::OnBlownUp()
{
	// TODO: 在此添加命令处理程序代码
	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();
	if (m_scale_idx>=0&&m_scale_idx<8)
	{
		m_scale_idx = m_scale_idx + 1;
		m_imgscale = m_imgscale * g_scale_arr[m_scale_idx];
		img_width = img_width * g_scale_arr[m_scale_idx];
		img_height = img_height * g_scale_arr[m_scale_idx];	
		m_stamppoint.x = m_stamppoint.x * g_scale_arr[m_scale_idx];	
		m_stamppoint.y = m_stamppoint.y * g_scale_arr[m_scale_idx];	
		m_stamp_r = m_stamp_r * g_scale_arr[m_scale_idx];
		 
		CImage newimage;
		ResizeImage(m_img,img_width,img_height,newimage);
		ImageCopy(newimage,m_img);
		newimage.Destroy();
		ResetScrollInfo();
		Invalidate();
	}
	else
	{
		MessageBox("已经放大到最大");
	}
}


void CButtonPic::OnBlownDown()
{
	// TODO: 在此添加命令处理程序代码
	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();
	if (m_scale_idx<=8&&m_scale_idx>0)
	{
		m_imgscale = m_imgscale / g_scale_arr[m_scale_idx];
		img_width = img_width / g_scale_arr[m_scale_idx];
		img_height = img_height / g_scale_arr[m_scale_idx];
		m_stamppoint.x = m_stamppoint.x / g_scale_arr[m_scale_idx];	
		m_stamppoint.y = m_stamppoint.y / g_scale_arr[m_scale_idx];	
		m_stamp_r = m_stamp_r / g_scale_arr[m_scale_idx];
		m_scale_idx = m_scale_idx - 1;	
		CImage newimage;
		ResizeImage(m_img,img_width,img_height,newimage);
		ImageCopy(newimage,m_img);
		newimage.Destroy();
		ResetScrollInfo();
		Invalidate();
	}
	else
	{
		MessageBox("已经缩放到最小");
	}
}


void CButtonPic::OnRightSize()
{
	// TODO: 在此添加命令处理程序代码
	//ShowImage(m_imgpath,m_parent_wnd);
	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();
	double d_scale = m_imgscale / m_rightscale;
	m_imgscale = m_rightscale;
	m_scale_idx = 0 ;
	img_width = img_width / d_scale;
	img_height = img_height / d_scale;
	m_stamppoint.x = m_stamppoint.x / d_scale;	
	m_stamppoint.y = m_stamppoint.y / d_scale;	
	m_stamp_r = m_stamp_r / d_scale;
	CImage newimage;
	ResizeImage(m_img,img_width,img_height,newimage);
	ImageCopy(newimage,m_img);
	newimage.Destroy();
	ResetScrollInfo();
	Invalidate();	
		
	
}


void CButtonPic::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CRect rc;
	this->GetClientRect(&rc);
	switch(nSBCode)
	{
	case SB_LEFT:

		m_scrollpos_w = 0;
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);		
		break;
	case SB_LINELEFT:
	case SB_PAGELEFT:
		m_scrollpos_w -= m_onestep;

		if(m_scrollpos_w<0)
		{
			m_scrollpos_w = 0;
		}
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		break;
	case SB_LINERIGHT:
	case SB_PAGERIGHT:
		if (m_img.GetWidth()-rc.Width()<=(m_scrollpos_w+m_onestep)||
			m_img.GetWidth()<rc.Width())
		{
			break;
		}
		m_scrollpos_w += m_onestep;

		if(m_scrollpos_w>m_scrollmaxsize_w)
		{
			m_scrollpos_w = m_scrollmaxsize_w;
		}
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		break;
	case SB_RIGHT:

		m_scrollpos_w = m_scrollmaxsize_w;
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		if (m_img.GetWidth()-rc.Width()>=nPos&&
			m_img.GetWidth()>rc.Width())
		{
			m_scrollpos_w = nPos;
			this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		}
		
		break;
	default:
		break;
	}
	DrawImage();
	CButton::OnHScroll(nSBCode, nPos, pScrollBar);
}


void CButtonPic::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CRect rc;
	this->GetClientRect(&rc);
	switch(nSBCode)
	{
	case SB_LEFT:

		m_scrollpos_h = 0;
		this->SetScrollPos(SB_VERT,m_scrollpos_h);		
		break;
	case SB_LINELEFT:
	case SB_PAGELEFT:

		m_scrollpos_h -= m_onestep;

		if(m_scrollpos_h<0)
		{
			m_scrollpos_h = 0;
		}
		this->SetScrollPos(SB_VERT,m_scrollpos_h);
		break;
	case SB_LINERIGHT:
	case SB_PAGERIGHT:
		if (m_img.GetHeight()-rc.Height()<=m_scrollpos_h+m_onestep||
			m_img.GetHeight()<rc.Height())
		{
			break;
		}
		m_scrollpos_h += m_onestep;

		if(m_scrollpos_h>m_scrollmaxsize_h)
		{
			m_scrollpos_h = m_scrollmaxsize_h;
		}
		this->SetScrollPos(SB_VERT,m_scrollpos_h);
		break;
	case SB_RIGHT:

		m_scrollpos_h = m_scrollmaxsize_h;
		this->SetScrollPos(SB_VERT,m_scrollpos_h);
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		if (m_img.GetHeight()-rc.Height()>=nPos&&
			m_img.GetHeight()>rc.Height())
		{
			m_scrollpos_h = nPos;
			this->SetScrollPos(SB_VERT,m_scrollpos_h);
		}
		
		break;
	default:
		break;
	}
	DrawImage();
	CButton::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CButtonPic::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	std::stringstream strbuf;
	CString msgbox = "";
	if (selstampflag)
	{		
		CRect rc;
		this->GetClientRect(&rc);
		int move_x = (rc.Width() - m_img.GetWidth())/2>0?(rc.Width() - m_img.GetWidth())/2:0;
		int move_y = (rc.Height() - m_img.GetHeight())/2>0?(rc.Height() - m_img.GetHeight())/2:0;
		ScreenToClient(&rc);
		if (point.x>m_stamp_r+move_x&&point.x< rc.Width()-m_stamp_r-move_x
			&& point.y>m_stamp_r+move_y &&point.y<rc.Height()-m_stamp_r-move_y)
		{
			m_stamppoint.x = point.x + m_scrollpos_w-move_x;
			m_stamppoint.y = point.y +m_scrollpos_h-move_y;

			selstampflag = false;
			m_angle = m_angle%360>0?m_angle%360:m_angle%360+360;
			double d_scale = m_imgscale/m_rightscale;
			m_realstamppoint.x = (m_stamppoint.x-m_img.GetWidth()/2)*m_rightscale/d_scale;
			m_realstamppoint.y = (m_stamppoint.y-m_img.GetHeight()/2)*m_rightscale/d_scale;
			strbuf << "你选择了用印点("<< m_realstamppoint.x << "," << m_realstamppoint.y <<"),准备开始用印!";
			msgbox = "确定";
		}
		else
		{
			strbuf << "选择的盖章点("<< m_stamppoint.x << "," << m_stamppoint.y <<")超出用印范围,请重新选择!";
			msgbox = "错误";			
		}
		string strmsg;
		strbuf >> strmsg;
		MessageBox(strmsg.c_str(),msgbox);
	}
	Invalidate();
	CButton::OnLButtonUp(nFlags, point);
}


void CButtonPic::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (selstampflag)
	{
		CRect rc;
		this->GetClientRect(&rc);
		int move_x = (rc.Width() - m_img.GetWidth())/2>0?(rc.Width() - m_img.GetWidth())/2:0;
		int move_y = (rc.Height() - m_img.GetHeight())/2>0?(rc.Height() - m_img.GetHeight())/2:0;
		ScreenToClient(&rc);
		if (point.x>m_stamp_r+move_x&&point.x< rc.Width()-m_stamp_r-move_x
			&& point.y>m_stamp_r+move_y &&point.y<rc.Height()-m_stamp_r-move_y)
		{
			HCURSOR hCur = LoadCursor( NULL,IDC_CROSS) ;
			::SetCursor(hCur);
		}
	}
	CButton::OnMouseMove(nFlags, point);
}

图像旋转头文件:CIProcess.h

#pragma once
#include <atlimage.h>
namespace CIProcess
{
	struct IMAGEPARAMENT {          
		int     nWidth;   
		int     nHeight;   
		int     nBitCount;   
		int     nBytesPerLine;   
		int     nBytesPerPixel;   
		int     nNumColors;   
		int     nSize;   
	};   
	void  GetImageParament(CImage *pImg,struct IMAGEPARAMENT *ppImgParam);   
	int   InImage(CImage *pImg,int x,int y);   
	void  SetRectValue(CImage *pImg,int x,int y,int Dx,int Dy,BYTE *buf); 
	void  GetAllPalette(CImage *pImg,RGBQUAD *ColorTab);   
	void  SetAllPalette(CImage *pImg,RGBQUAD *ColorTab);   
	int   PaletteType(RGBQUAD   *ColorTab);   
	int   ImageType(CImage *pImgm);   
	void RotateCimage(CImage *Imgm, CImage *Imgn, double alpha);  

};

图像旋转源码:CIProcess.cpp

#include "StdAfx.h"
#include "CIProcess.h"
#include <math.h>  

void CIProcess::GetImageParament(CImage *pImg,struct IMAGEPARAMENT *ppImgParam)  
{  
	if (pImg->IsNull()) return;  

	ppImgParam->nWidth   = pImg->GetWidth();      //图像宽度  
	ppImgParam->nHeight   = pImg->GetHeight();        //图像高度  
	ppImgParam->nBitCount  = pImg->GetBPP();      //每像素位数  
	ppImgParam->nBytesPerLine   = (pImg->GetWidth()*pImg->GetBPP()+31)/32*4;   //每行字节数  
	ppImgParam->nBytesPerPixel   = pImg->GetBPP()/8;      //每像素字节数  
	if (pImg->GetBPP()<=8)   
		ppImgParam->nNumColors= 1 << pImg->GetBPP();        //调色板单元数  
	else   
		ppImgParam->nNumColors= 0;  
	ppImgParam->nSize  = ppImgParam->nBytesPerLine*ppImgParam->nHeight;        //像素总字节数  
}  

int  CIProcess::InImage(CImage *pImg,int x,int y)  
{  
	struct  IMAGEPARAMENT  P;  

	GetImageParament(pImg,&P);  
	if ((x<0)||(y<0)||(x>=P.nWidth)||(y>=P.nHeight))  return 0;  
	else  return 1;  
}  
void CIProcess::SetRectValue(CImage *pImg,int x,int y,int Dx,int Dy,BYTE *buf)  
{  
	struct  IMAGEPARAMENT  P;  
	BYTE    *lp;  
	int     i,dw,dh,x1,y1,alpha,delta,Dxb,dwb;  

	GetImageParament(pImg,&P);  
	if (P.nBitCount<8) return;  
	x1=x;  
	y1=y;  
	alpha=delta=0;  
	if (x<0) {   
		alpha=-x;    x1=0;  
	}  
	if (y<0) {   
		delta=-y;    y1=0;  
	}  
	if (!InImage(pImg,x1,y1)) return;  
	dw=min(Dx,(int) P.nWidth-x1);      
	dh=min(Dy,(int) P.nHeight-y1);  
	dw -= alpha;  
	dh -= delta;  

	Dxb = Dx*P.nBytesPerPixel;  
	dwb = dw*P.nBytesPerPixel;  
	lp = (BYTE*) pImg->GetPixelAddress(x1,y1);  
	buf += (delta*Dx+alpha)*P.nBytesPerPixel;  
	for (i=0;i<dh;i++) {  
		memcpy(lp,buf,dwb);    
		buf += Dxb;   
		lp -= P.nBytesPerLine;  
	}  
} 
void CIProcess::GetAllPalette(CImage *pImg,RGBQUAD *ColorTab)  
{  
	struct  IMAGEPARAMENT P;  

	GetImageParament(pImg,&P);  
	pImg->GetColorTable(0, P.nNumColors, ColorTab);  
}  

void CIProcess::SetAllPalette(CImage *pImg, RGBQUAD *ColorTab)  
{  
	struct  IMAGEPARAMENT P;  

	GetImageParament(pImg,&P);  
	pImg->SetColorTable(0, P.nNumColors, ColorTab);  
}
int   CIProcess::PaletteType(RGBQUAD  *ColorTab)  
{  
	int     i,k,m,n,r,g,b;  

	m=n=0;  
	for (i=0; i<256; i++)  
	{  
		r = ColorTab[i].rgbRed;  
		g = ColorTab[i].rgbGreen;  
		b = ColorTab[i].rgbBlue;  
		if ((r != g)||(r != b)) m=0;  
		if ((i>0)&&(r>ColorTab[i-1].rgbRed)) m++;  
		if (r+g+b==0) n++;  
	}  
	k=3;  
	if (m == 255) k=2;      
	else  if (256-n==1) k=0;                       
	else  if (256-n==15) k=1;                       
	return(k);  
}  

int CIProcess::ImageType(CImage *pImgm)            //判断图像类型   
{  
	RGBQUAD ColorTab[256];  
	int     k;  

	if (pImgm->IsNull()) return(0);  

	switch(pImgm->GetBPP())  
	{  
	case 1:  k=0;   break;   
	case 4:  k=1;   break;   
	case 8:  k=3;   break;   
	default: k=4;   break;   
	}  

	if (k==3)                    
	{  
		pImgm->GetColorTable(0,256,ColorTab);  
		k=PaletteType(ColorTab);  
	}  
	return(k);  
} 
void CIProcess::RotateCimage(CImage *Imgm, CImage *Imgn, double alpha)  
{  
	IMAGEPARAMENT P;   
	RGBQUAD ColorTab[256];   
	int i, j, ww, Xd, Yd, Dx, Dy,nSize;   
	double centerx, centery, sintheta, costheta;   
	double X1, Y1, X2, Y2, theta, xx, yy, rr;   
	BYTE **list, *sc;   
	int x1, y1, x2, y2, flag;   
	double p, q, a, b, c, d, t1, t2, t3;   

	if (ImageType(Imgm) == 2)  flag = 1; //flag为标志位,当取值为1时,表示双线性内插法 ,此时图像类型为灰阶图像  
	else flag = 0; //0表示最近邻点法   
	GetImageParament(Imgm, &P);   

	Dx = P.nWidth;   
	Dy = P.nHeight;   
	nSize = 0;  
	if (Dx < Dy)  
	{  
		nSize = Dy;  
	}  
	else  
	{  
		nSize = Dx;  
	}  
	int nLineBytes = (nSize * P.nBitCount + 31) / 32 * 4;  

	//还有一点要修改,不然当图像高度远大于宽度时会崩溃  
	sc = (BYTE*) malloc(2 * nLineBytes);    // * P.nBytesPerLine); //申请工作单元   
	//  
	list = (BYTE**) malloc(Dy * sizeof(BYTE*)); //对原位图建立二维数组   
	for (i = 0; i < Dy; i++)   
		list[i] = (BYTE*)  Imgm ->GetPixelAddress(0, i);   

	centerx = Dx / 2; //计算位图中心位置   
	centery = Dy / 2;   
	rr = sqrt(centerx * centerx + centery *centery); //计算对角线长度   

	theta = atan((double) centery / (double) centerx);   
	alpha = alpha*3.14159265/180;
	X1 = fabs(rr * cos(alpha + theta)) + 0.5;   
	Y1 = fabs(rr * sin(alpha + theta)) + 0.5;   
	X2 = fabs(rr * cos(alpha - theta)) + 0.5;   
	Y2 = fabs(rr * sin(alpha - theta)) + 0.5;   

	if (X2 > X1) X1 = X2; //得外接矩形宽度   
	if (Y2 > Y1) Y1 = Y2; //外接矩形高度   
	ww = (int) (2 * X1);   

	Imgn ->Destroy();   

	Imgn ->Create(ww, (int) (2 * Y1), P.nBitCount ); //建立结果位图   
	if (P.nBitCount == 8)   
	{   
		GetAllPalette(Imgm, ColorTab);   
		//修改一,设置目标调色板  
		SetAllPalette(Imgn, ColorTab); //复制调色板   
	}   
	sintheta = sin(alpha);   
	costheta = cos(alpha);   

	for (j = (int) (centery - Y1), Yd = 0; j <= (centery + Y1); j++, Yd++)   
	{   
		if (P.nBitCount == 8)   
			memset (sc, 0, ww); //256色位图像素行置背景值   
		else   
			memset(sc, 0, ww * P.nBytesPerPixel); //真彩色位图像素行置背景值   

		for (i = (int) (centerx - X1), Xd = 0; i <= centerx + X1; i++, Xd += P.nBytesPerPixel)   
		{   
			xx = centerx + costheta * (i - centerx) + sintheta * (j - centery);   
			yy = centery - sintheta * (i - centerx) + costheta * (j - centery);   
			x1 = (int) xx;   
			x2 = x1 + 1;   
			p = xx - x1;   
			y1 = (int) yy;   
			y2 = y1 + 1;   
			q = yy - y1;   
			if (((x1 < 0)||(x2 >= P.nWidth )||(y1 < 0)||(y2 >= P.nHeight )))   
				continue;   
			if (flag == 0)   
			{   
				if (q > 0.5)  y1 = y2;   
				if (p > 0.5)  x1 = x2;   
				//修改二, sc[Xd]  
				memcpy(&sc[Xd], &list[y1][x1 * P.nBytesPerPixel], P.nBytesPerPixel); //从源位图复制像素数据   
			}   
			else   
			{ // flag等于1,双线性内插法   
				a = (double) list[y1][x1]; //从源位图取数据   
				b = (double) list[y1][x2];   
				c = (double) list[y2][x1];   
				d = (double) list[y2][x2];   
				t1 = (1 - p) * a + p * b; //双线性内插计算   
				t2 = (1 - p) * c + p * d;   
				t3 = (1 - q) * t1 + q * t2;   
				//修改三  
				sc[Xd] = (BYTE) t3;   
			}   
		}   
		SetRectValue(Imgn, 0, Yd, ww, 1, sc);   
	}   
	free(list); //释放工作单元   
	free(sc);  
} 

 

 

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
moki_oschina
粉丝 24
博文 169
码字总数 22482
作品 0
成都
程序员
VC中动态添加控件

动态控件是指在需要时由Create()创建的控件,这与预先在对话框中放置的控件是不同的。   一、创建动态控件:   为了对照,我们先来看一下静态控件的创建。   放置静态控件时必须先建立...

郝槟楠 ⋅ 2011/12/01 ⋅ 0

visual c+ 2010开发的播放器

VC2010可谓是微软的王牌产品,它以强大的功能而赢得了广大程序员的爱好。而用VC的AppWizard、ClassWizard和其中的各种控件可以方便地建立应用程序。 本文就介绍用VC6.0自带的一个ActiveX控件...

crossmix ⋅ 2015/04/15 ⋅ 0

利用 CStatic 开发自绘控件

棋牌休闲大厅客户端因采用MFC而不是用DX来做UI。因为MFC中对于自绘控件弄得比较麻烦,在研究了一段图片按钮和一些自绘控件后,我打算用CStatic做基类进行派生写一些自已用的界面控件。因为以...

长平狐 ⋅ 2012/11/19 ⋅ 0

ModifyStyle函数

1.作用:Call this member function to modify a window's style. 2.函数原型: BOOL ModifyStyle ( DWORD dwRemove, DWORD dwAdd, UINT nFlags ); 3.参数含义: dwRemove指定要删除的扩展属性,......

云栖希望。 ⋅ 2017/12/04 ⋅ 0

利用 CStatic 开发自绘控件

棋牌休闲大厅客户端因采用MFC而不是用DX来做UI。因为MFC中对于自绘控件弄得比较麻烦,在研究了一段图片按钮和一些自绘控件后,我打算用CStatic做基类进行派生写一些自已用的界面控件。因为以...

长平狐 ⋅ 2013/03/19 ⋅ 0

c++界面开发随笔

对于界面开发有所涉猎的朋友,应该能明白我下面要说的东西。 1、MFC很早就出来,功能很全面、控件很多,文档全,因此带来的问题,类特多、入门难、界面丑、扩展难。如果想自定义控件,那至少...

ouloba ⋅ 2016/06/28 ⋅ 0

可判断焦点是否停在输入窗口

 GetFocus() 功能确定当前焦点位于哪个控件上。 语法GetFocus ( ) 返回值GraphicObject。函数执行成功时返回当前得到焦点控件的引用,发生错误时返回无效引用。用法应用程序利用IsValid()函...

云栖希望。 ⋅ 2017/12/04 ⋅ 0

支持Delphi/C++Builder的文字处理控件TRichView

TRichView 是一套支持Delphi/C++Builder的控件,有和Word相似的功能,主要用于编辑、显示和打印超文本文档。该控件支持各种各样不同的属性(字体、下标和上标,自定义下拉列表,文本背景颜色...

yidongkaifa ⋅ 2014/04/22 ⋅ 0

VC中Radio控件的用法

先为对话框加上2个radio button,分别是Radio1和Radio2。 问题1:如何让Radio1或者Radio2默认选上?如何知道哪个被选上了? 关键是选上,“默认”只要放在OnInitDialog()即可。三种方法可以让...

barsoom ⋅ 2012/11/19 ⋅ 0

iOS 切换视图--DVSwitch

DVSwitch 是可定制的,基于 UISwitch 和 UISegmentedControl 的控件,使用 Objective-C 编写。 DVSwitch 灵感来源于 UISwitch 和 UISegmentedControl,目标如下: 简单定制非常漂亮的动画控件...

叶秀兰 ⋅ 2014/10/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

用ZBLOG2.3博客写读书笔记网站能创造今日头条的辉煌吗?

最近两年,著名的自媒体网站今日头条可以说是火得一塌糊涂,虽然从目前来看也遇到了一点瓶颈,毕竟发展到了一定的规模,继续增长就更加难了,但如今的今日头条规模和流量已经非常大了。 我们...

原创小博客 ⋅ 32分钟前 ⋅ 0

MyBatis四大核心概念

本文讲解 MyBatis 四大核心概念(SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper)。 MyBatis 作为互联网数据库映射工具界的“上古神器”,训有四大“神兽”,谓之:Sql...

waylau ⋅ 52分钟前 ⋅ 0

以太坊java开发包web3j简介

web3j(org.web3j)是Java版本的以太坊JSON RPC接口协议封装实现,如果需要将你的Java应用或安卓应用接入以太坊,或者希望用java开发一个钱包应用,那么用web3j就对了。 web3j的功能相当完整...

汇智网教程 ⋅ 今天 ⋅ 0

2个线程交替打印100以内的数字

重点提示: 线程的本质上只是一个壳子,真正的逻辑其实在“竞态条件”中。 举个例子,比如本题中的打印,那么在竞态条件中,我只需要一个方法即可; 假如我的需求是2个线程,一个+1,一个-1,...

Germmy ⋅ 今天 ⋅ 0

Springboot2 之 Spring Data Redis 实现消息队列——发布/订阅模式

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式,这里利用redis消息“发布/订阅”来简单实现订阅者模式。 实现之前先过过 redis 发布订阅的一些基础概念和操...

Simonton ⋅ 今天 ⋅ 0

error:Could not find gradle

一.更新Android Studio后打开Project,报如下错误: Error: Could not find com.android.tools.build:gradle:2.2.1. Searched in the following locations: file:/D:/software/android/andro......

Yao--靠自己 ⋅ 昨天 ⋅ 0

Spring boot 项目打包及引入本地jar包

Spring Boot 项目打包以及引入本地Jar包 [TOC] 上篇文章提到 Maven 项目添加本地jar包的三种方式 ,本篇文章记录下在实际项目中的应用。 spring boot 打包方式 我们知道,传统应用可以将程序...

Os_yxguang ⋅ 昨天 ⋅ 0

常见数据结构(二)-树(二叉树,红黑树,B树)

本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自coursera上普林斯顿的课程《Algorithms, Part I》中的Slides 相关命题的证明可参考《算法(第...

浮躁的码农 ⋅ 昨天 ⋅ 0

android -------- 混淆打包报错 (warning - InnerClass ...)

最近做Android混淆打包遇到一些问题,Android Sdutio 3.1 版本打包的 错误如下: Android studio warning - InnerClass annotations are missing corresponding EnclosingMember annotation......

切切歆语 ⋅ 昨天 ⋅ 0

eclipse酷炫大法之设置主题、皮肤

eclipse酷炫大法 目前两款不错的eclipse 1.系统设置 Window->Preferences->General->Appearance 2.Eclipse Marketplace下载【推荐】 Help->Eclipse Marketplace->搜索‘theme’进行安装 比如......

anlve ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部