📄 bitmapwnd.cpp
字号:
// BitmapWnd.cpp : implementation file
//
#include "stdafx.h"
#include "btnetsc.h"
#include "BitMapWnd.h"
#include <atlimage.h>
#include "stroke.h"
// CBitmapWnd
CBitmapWnd::CBitmapWnd()
{
m_hBitmap = 0;
m_pImg = NULL;
m_Pen.CreatePen(PS_SOLID, 3, RGB(255,0,0));
}
CBitmapWnd::~CBitmapWnd()
{
DeleteStrokes();
if (m_pImg)
{
m_pImg->Detach();
delete m_pImg;
}
}
void CBitmapWnd::DeleteStrokes()
{
while (!m_strokeList.IsEmpty())
{
delete m_strokeList.RemoveHead();
}
}
BEGIN_MESSAGE_MAP(CBitmapWnd, CStatic)
//{{AFX_MSG_MAP(CBitmapWnd)
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CBitmapWnd::SetBitmap(HBITMAP hbitmap)
{
m_hBitmap = hbitmap;
if (m_pImg)
{
m_pImg->Detach();
delete m_pImg;
}
m_pImg = new CImage();
m_pImg->Attach(hbitmap);
// get source bitmap dimensions
int nWidthSource = m_pImg->GetWidth();
int nHeightSource = m_pImg->GetHeight();
// get target window dimensions
RECT rect;
::GetClientRect(this->m_hWnd,&rect);
int nWidthTarget = rect.right-rect.left;
int nHeightTarget = rect.bottom-rect.top;
// Don't stretch the bitmap. If it is smaller than
// the window, use make the target area the same
// size as the bitmap.
if (nWidthTarget > nWidthSource
&& nHeightTarget > nHeightSource)
{
m_nX = nWidthSource;
m_nY = nHeightSource;
}
else {
// We are going to shrink the bitmap, but
// we want to preserve the aspect ratio.
float nWidthRatio
= (float)nWidthSource/(float)nWidthTarget;
float nHeightRatio
= (float)nHeightSource/(float)nHeightTarget;
if (nHeightRatio > nWidthRatio)
{
// Shrink the height to fit window.
// Shrink the width to preserve aspect ratio.
m_nX = (int)(((float)nHeightTarget*(float)nWidthSource)
/(float)nHeightSource);
m_nY = nHeightTarget;
}
else if (nWidthRatio > nHeightRatio)
{
// Shrink the width to fit window.
// Shrink the height to preserve aspect ratio.
m_nX = nWidthTarget;
m_nY = (int)(((float)nWidthTarget*(float)nHeightSource)
/(float)nWidthSource);
}
}
DeleteStrokes();
}
void CBitmapWnd::OnPaint()
{
if (m_hBitmap)
{
CPaintDC dc(this);
m_pImg->StretchBlt(dc.m_hDC,
0,0,
m_nX, m_nY,
0,0, m_pImg->GetWidth(),m_pImg->GetHeight(),
SRCCOPY);
POSITION pos = m_strokeList.GetHeadPosition();
CPen* pOldPen = dc.SelectObject(&m_Pen);
while (pos != NULL)
{
CStroke* pStroke = m_strokeList.GetNext(pos);
pStroke->DrawStroke(&dc);
}
dc.SelectObject(pOldPen);
}
else
{
CStatic::OnPaint();
}
}
HBITMAP CBitmapWnd::GetBitmap()
{
CClientDC dc(this);
CDC MemDC;
MemDC.CreateCompatibleDC(&dc);
HBITMAP hBitmap = ::CreateCompatibleBitmap(dc.m_hDC,
m_pImg->GetWidth(),m_pImg->GetHeight());
MemDC.SelectObject(hBitmap);
m_pImg->BitBlt(MemDC,
0,0,
m_pImg->GetWidth(),m_pImg->GetHeight(),
0,0,
SRCCOPY);
RECT rect;
::GetClientRect(this->m_hWnd,&rect);
float nClientWidth = (float) m_nX;// rect.right-rect.left;
float nClientHeight = (float) m_nY; // rect.bottom-rect.top;
float fXFactor = ((float) m_pImg->GetWidth())/nClientWidth;
float fYFactor = ((float) m_pImg->GetHeight())/nClientHeight;
POSITION pos = m_strokeList.GetHeadPosition();
CPen* pOldPen = MemDC.SelectObject(&m_Pen);
while (pos != NULL)
{
CStroke* pStroke = m_strokeList.GetNext(pos);
pStroke->DrawStroke(&MemDC, fXFactor, fYFactor);
}
MemDC.SelectObject(pOldPen);
/*
// Save as a JPEG
ATL::CImage img;
img.Attach(hBitmap);
img.Save("c:\\temp\\a.jpeg", Gdiplus::ImageFormatJPEG);
img.Detach();
*/
return hBitmap;
}
// CBitmapWnd message handlers
void CBitmapWnd::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_hBitmap) return;
// Mouse movement is interesting in the Scribble application
// only if the user is currently drawing a new stroke by dragging
// the captured mouse.
if (GetCapture() != this)
return; // If this window (view) didn't capture the mouse,
// then the user isn't drawing in this window.
CClientDC dc(this);
m_pStrokeCur->m_pointArray.Add(point);
// Draw a line from the previous detected point in the mouse
// drag to the current point.
CPen* pOldPen = dc.SelectObject(&m_Pen);
dc.MoveTo(m_ptPrev);
dc.LineTo(point);
dc.SelectObject(pOldPen);
m_ptPrev = point;
return;
}
void CBitmapWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
if (!m_hBitmap) return;
m_pStrokeCur = NewStroke();
// Add first point to the new stroke
m_pStrokeCur->m_pointArray.Add(point);
SetCapture(); // Capture the mouse until button up.
m_ptPrev = point; // Serves as the MoveTo() anchor point for the
// LineTo() the next point, as the user drags the
// mouse.
return;
}
void CBitmapWnd::OnLButtonUp(UINT nFlags, CPoint point)
{
if (!m_hBitmap) return;
// Mouse button up is interesting in the Scribble application
// only if the user is currently drawing a new stroke by dragging
// the captured mouse.
if (GetCapture() != this)
return; // If this window (view) didn't capture the mouse,
// then the user isn't drawing in this window.
CClientDC dc(this);
CPen* pOldPen = dc.SelectObject(&m_Pen);
dc.MoveTo(m_ptPrev);
dc.LineTo(point);
dc.SelectObject(pOldPen);
m_pStrokeCur->m_pointArray.Add(point);
// Tell the stroke item that we're done adding points to it.
// This is so it can finish computing its bounding rectangle.
m_pStrokeCur->FinishStroke();
ReleaseCapture(); // Release the mouse capture established at
// the beginning of the mouse drag.
return;
}
CStroke* CBitmapWnd::NewStroke()
{
// I'm ignoring the pen width here
CStroke* pStrokeItem = new CStroke(1);
m_strokeList.AddTail(pStrokeItem);
return pStrokeItem;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -