需求:要在标签模板上加上文字、条型码、二维码 找准坐标和字体大小
我生成标签时,需要对齐和 调文字字体大小。这工具微调 能快速知道位置 和字体大小。
标签设计(点击图片,上下左右箭头移动 +或-调字体)
已经够用了,滚动条还没完全实现,如果能拖动文字、条型码、二维码到上面就更好了,就是有太多参数需要设置。
在MFC(Microsoft Foundation Classes)中,要实现在一个图片控件上移动鼠标时显示图片控件内鼠标位置的水平和垂直辅助线,你可以通过处理鼠标移动事件来绘制这些辅助线。以下是一个简化的示例,展示了如何在一个继承自CStatic
的类中实现这个功能。
首先,你需要创建一个新的类,继承自CStatic
,并在这个类中处理WM_MOUSEMOVE
消息来绘制辅助线。
// PictureControl.h
#pragma once
#include <afxwin.h>
class CPictureControl : public CStatic
{
public:
CPictureControl();
virtual ~CPictureControl();
protected:
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
DECLARE_MESSAGE_MAP()
void DrawCrossHair(CPoint point);
};
在.cpp
文件中,你需要实现OnMouseMove
和DrawCrossHair
方法。OnMouseMove
方法会在鼠标移动时被调用,而DrawCrossHair
方法用于在控件上绘制辅助线。
// PictureControl.cpp
#include "PictureControl.h"
BEGIN_MESSAGE_MAP(CPictureControl, CStatic)
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
CPictureControl::CPictureControl()
{
}
CPictureControl::~CPictureControl()
{
}
void CPictureControl::OnMouseMove(UINT nFlags, CPoint point)
{
CStatic::OnMouseMove(nFlags, point);
// 绘制辅助线
DrawCrossHair(point);
}
void CPictureControl::DrawCrossHair(CPoint point)
{
CDC* pDC = GetDC();
CRect rect;
GetClientRect(&rect);
// 保存当前DC状态
int nSavedDC = pDC->SaveDC();
// 设置ROP模式为R2_NOT,这样可以用相同的操作来清除线条
pDC->SetROP2(R2_NOT);
// 绘制水平线
pDC->MoveTo(0, point.y);
pDC->LineTo(rect.right, point.y);
// 绘制垂直线
pDC->MoveTo(point.x, 0);
pDC->LineTo(point.x, rect.bottom);
// 恢复DC状态
pDC->RestoreDC(nSavedDC);
ReleaseDC(pDC);
}
最后,确保你的对话框或窗口中的图片控件使用了这个CPictureControl
类。如果你是在对话框中使用,你可能需要在对话框的头文件中声明一个CPictureControl
成员变量,并在对话框的OnInitDialog
方法中将这个控件与实际的控件ID关联起来。
// 在对话框头文件中
CPictureControl m_picControl;
// 在对话框的OnInitDialog方法中
m_picControl.SubclassDlgItem(IDC_PICTURE_CONTROL, this);
请注意,这个示例仅提供了基本的实现框架。根据你的具体需求,你可能需要对代码进行调整,比如在绘制辅助线之前清除之前的线条,或者处理图片的缩放等问题。
最后绑定ID (m_picControl.SubclassDlgItem(IDC_PICTURE_CONTROL, this);)也可以这样
MFC调用自定义控件类OnMouseMove不响应
必须要将Notify设为True才行。
画出来了,但是没有清除鼠标移动前的所有辅助线痕迹
改成点击
必须要将Notify设为True才行。
// CDlgLableDesign.cpp: 实现文件
//
#include "pch.h"
#include "afxdialogex.h"
#include "CDlgLableDesign.h"
#include "Resource.h"
#define MAX_SCROLL_POS 2000
typedef struct Para
{
char templateName[200];
LONG fontHeight=82;
CPoint point;
}Para;
static Para para = {0};
// CDlgLableDesign 对话框
IMPLEMENT_DYNAMIC(CDlgLableDesign, CDialogEx)
CDlgLableDesign::CDlgLableDesign(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG_LabelDesign, pParent)
{
}
CDlgLableDesign::~CDlgLableDesign()
{
}
void CDlgLableDesign::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_LOG2, m_editDisplay);
//DDX_Control(pDX, IDC_STATIC_IMAGE, m_pictureCtrl);
}
BEGIN_MESSAGE_MAP(CDlgLableDesign, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON_PRINT_OUTBOX, &CDlgLableDesign::OnBnClickedButtonPrintOutbox)
ON_WM_TIMER()
// ON_WM_MOUSEMOVE()
// ON_WM_PAINT()
ON_STN_CLICKED(IDC_STATIC_IMAGE, &CDlgLableDesign::OnClickedStaticImage)
//ON_WM_VSCROLL()
ON_WM_CLOSE()
END_MESSAGE_MAP()
void CDlgLableDesign::Log(CString szInfo)
{
logger.INFO_F(szInfo.GetBuffer(0));
CString strInfo;
m_editDisplay.GetWindowText(strInfo);
int nLength = strInfo.GetLength();
m_editDisplay.SetSel(nLength, nLength, FALSE);
m_editDisplay.SetFocus();
m_editDisplay.SetSel(-1, -1);
m_editDisplay.ReplaceSel(szInfo + "\r\n");
}
// CDlgLableDesign 消息处理程序
BOOL CDlgLableDesign::LoadImageToPictureControl(CString bmpPath)
{
CStatic* pPictureControl = (CStatic*)GetDlgItem(IDC_STATIC_IMAGE);
if (pPictureControl == nullptr || bmpPath.IsEmpty())
return FALSE;
// 加载图片
CImage image;
HRESULT hr = image.Load(bmpPath);
if (FAILED(hr))
{
Log("加载图片失败"+ bmpPath);
return FALSE;
}
// 获取图片大小
int nWidth = image.GetWidth();
int nHeight = image.GetHeight();
//Log("宽高 "+CString(to_string(nWidth).c_str())+" * " + CString(to_string(nHeight).c_str()) +" 转为mm " + CString(to_string(nWidth* PixToMm600).c_str()) + " * " + CString(to_string(nHeight * PixToMm600).c_str()));
// 调整控件大小以适应图片
//CRect rect;
//pPictureControl->GetWindowRect(&rect);
pPictureControl->MoveWindow(208, 10, nWidth, nHeight);
// 获取控件的DC
CDC* pDC = pPictureControl->GetDC();
if (pDC == nullptr)
return FALSE;
// 创建兼容DC
CDC dcImage;
if (!dcImage.CreateCompatibleDC(pDC))
return FALSE;
// 选择图片到DC
CBitmap bmp;
bmp.Attach(image.Detach());
CBitmap* pOldBmp = dcImage.SelectObject(&bmp);
// 将图片绘制到控件上
pDC->BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);
// 清理
dcImage.SelectObject(pOldBmp);
pPictureControl->ReleaseDC(pDC);
//CImage image;
//HRESULT hResult = image.Load(_T(bmpPath)); // 加载图片
//if (SUCCEEDED(hResult))
//{
// // 获取Picture Control的句柄
// CStatic* pPictureControl = (CStatic*)GetDlgItem(IDC_STATIC_IMAGE);
// // 获取控件大小
// CRect rect;
// pPictureControl->GetClientRect(&rect);
// int controlWidth = rect.Width();
// int controlHeight = rect.Height();
// // 获取图片原始尺寸
// int imageWidth = image.GetWidth();
// int imageHeight = image.GetHeight();
// // 创建兼容的DC
// CDC* pDC = pPictureControl->GetDC();
// CDC memDC;
// memDC.CreateCompatibleDC(pDC);
// // 创建兼容的位图,并选入内存DC
// CBitmap bmp;
// bmp.CreateCompatibleBitmap(pDC, controlWidth, controlHeight);
// CBitmap* pOldbmp = memDC.SelectObject(&bmp);
// // 清空背景
// memDC.FillSolidRect(&rect, pDC->GetBkColor());
// // 使用CImage绘制到内存DC,这里使用缩放
// image.Draw(memDC.m_hDC, 0, 0, controlWidth, controlHeight, 0, 0, imageWidth, imageHeight);
// // 将内存DC绘制到控件上
// pDC->BitBlt(0, 0, controlWidth, controlHeight, &memDC, 0, 0, SRCCOPY);
// // 清理
// memDC.SelectObject(pOldbmp);
// ReleaseDC(pDC);
//}
//else
//{
// Log("图片加载失败:" + bmpPath);
//}
return TRUE;
}
BOOL ReadPara()
{
CString DebugPara = "";
GetPrivateProfileString("DEBUG", "DebugPara", "", DebugPara.GetBuffer(2000), 2000, configFileName); DebugPara.ReleaseBuffer();
if (DebugPara.GetLength() > 0)
{
utlStrToHex((BYTE*)¶, DebugPara.GetBuffer(), DebugPara.GetLength() / 2);
return TRUE;
}
return FALSE;
}
BOOL WritePara()
{
char DebugPara[4000] = {0};
utlHexToStr(DebugPara, (BYTE*)¶, sizeof(para));
if (WritePrivateProfileString("DEBUG", "DebugPara", DebugPara, configFileName))
{
return TRUE;
}
return FALSE;
}
BOOL CDlgLableDesign::OnInitDialog()
{
CDialogEx::OnInitDialog();
SetTimer(1, 100, NULL);
ShowWindow(SW_MAXIMIZE);
// 启用垂直滚动条
SetScrollRange(SB_VERT, 0, MAX_SCROLL_POS); // 假设滚动范围是0到200
//log位置自动长度
CRect rect;
GetDlgItem(IDC_EDIT_LOG2)->GetWindowRect(&rect);
GetClientRect(&rect);
rect.left = 8;
rect.top = 70;
rect.right = 8+195;
rect.bottom = rect.bottom -10;
GetDlgItem(IDC_EDIT_LOG2)->MoveWindow(&rect);
return TRUE; // return TRUE unless you set the focus to a control
// 异常: OCX 属性页应返回 FALSE
}
void CDlgLableDesign::OnBnClickedButtonPrintOutbox()
{
CFileDialog fileDlg(TRUE, _T("bmp"), NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, _T("Bitmap Files (*.bmp)|*.bmp||"));
if (fileDlg.DoModal() == IDOK)
{
memset((char*) & para, 0, sizeof(para));
memcpy(para.templateName, fileDlg.GetPathName().GetBuffer(), fileDlg.GetPathName().GetLength());
WritePara();
Log("加载模板:" + CString(para.templateName));
LoadImageToPictureControl(para.templateName); // 加载图片
}
}
void CDlgLableDesign::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nIDEvent == 1)
{
if (ReadPara())
{
if (strlen(para.templateName) > 0)
{
Log("加载模板:" + CString(para.templateName));
LoadImageToPictureControl(para.templateName); // 加载图片
}
}
KillTimer(1); // 销毁定时器
}
CDialogEx::OnTimer(nIDEvent);
}
//void CDlgLableDesign::OnMouseMove(UINT nFlags, CPoint point)
//{
// TODO: 在此添加消息处理程序代码和/或调用默认值
// 获取图片控件的位置和大小
// CRect rect;
// CStatic* pPictureControl = (CStatic*)GetDlgItem(IDC_STATIC_IMAGE);
// pPictureControl->GetWindowRect(&rect);
// ScreenToClient(&rect);
//
// 计算鼠标相对于图片控件的坐标
// int x = point.x - rect.left;
// int y = point.y - rect.top;
//
// 在log中输出坐标
// CString str;
// str.Format(_T("x: %d, y: %d"), x, y);
//
//
//
// 判断点是否在矩形内
// if (rect.PtInRect(point)) {
获取鼠标的当前位置
//CPoint mousePos = point;
绘制水平和垂直辅助线
//CClientDC dc(this);
//CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); // 红色辅助线
//dc.SelectObject(&pen);
//dc.MoveTo(mousePos.x, 0);
//dc.LineTo(mousePos.x, rect.Height());
//dc.MoveTo(0, mousePos.y);
//dc.LineTo(rect.Width(), mousePos.y);
重绘图片控件
//Invalidate();
//CClientDC dc(this);
设置字体
//CFont font;
//font.CreatePointFont(100, _T("Arial"), &dc);
//CFont* pOldFont = dc.SelectObject(&font);
使用TextOut函数在鼠标位置下方绘制文本
//dc.TextOut(point.x, point.y + 20, str);
清除原来的文本
CRect rect;
GetClientRect(&rect);
InvalidateRect(rect);
恢复原始字体
//dc.SelectObject(pOldFont);
Invalidate();
// }
//Log(str);
// CDialogEx::OnMouseMove(nFlags, point);
//}
void CDlgLableDesign::OnClickedStaticImage()
{
::GetCursorPos(¶.point); // 获取当前鼠标位置
ScreenToClient(¶.point); // 将屏幕坐标转换为窗口坐标
ShowImage();
}
void CDlgLableDesign::ShowImage()
{
LoadImageToPictureControl(para.templateName); // 加载图片
// 获取图片控件的位置和大小
CRect rect;
CStatic* pPictureControl = (CStatic*)GetDlgItem(IDC_STATIC_IMAGE);
pPictureControl->GetWindowRect(&rect);// 获取控件位置
ScreenToClient(&rect); // 将屏幕坐标转换为窗口坐标
// 计算鼠标相对于图片控件的坐标
int x = para.point.x - rect.left;
int y = para.point.y - rect.top;
// 在log中输出坐标
CString str;
str.Format(_T("%d, %d "), x, y);
Log(str);
SetClipboard(str);
//画辅助线
CDC* pDC = GetDC();
//CRect rect;
//GetClientRect(&rect);
// 保存当前DC状态
int nSavedDC = pDC->SaveDC();
DrawSomething(pDC, para.point.x, para.point.y); //画一些别的东西
// 设置ROP模式为R2_NOT,这样可以用相同的操作来清除线条
//pDC->SetROP2(R2_NOT);
CPen redPen;
redPen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); // 1像素宽的实线,红色
// 保存旧的画笔
CPen* pOldPen = pDC->SelectObject(&redPen);
// 绘制水平线
pDC->MoveTo(rect.left, para.point.y);
pDC->LineTo(rect.right, para.point.y);
// 绘制垂直线
pDC->MoveTo(para.point.x, rect.top);
pDC->LineTo(para.point.x, rect.bottom);
// 恢复旧的画笔
pDC->SelectObject(pOldPen);
// 恢复DC状态
pDC->RestoreDC(nSavedDC);
ReleaseDC(pDC);
}
BOOL CDlgLableDesign::DrawSomething(CDC* pDC,int x,int y)
{
// 设置字体
CFont font;
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
lf.lfHeight = para.fontHeight; // 字体大小
lf.lfWeight = FW_HEAVY; // 加粗
_tcscpy_s(lf.lfFaceName, ("黑体")); // 字体名称
font.CreateFontIndirect(&lf);
//font.CreatePointFont(240, "Arial", NULL);
CFont* pOldFont = pDC->SelectObject(&font);
SetBkMode(pDC->m_hDC, TRANSPARENT);
pDC->TextOut(x, y, _T("DEV1"));
pDC->SelectObject(pOldFont);
return TRUE;
}
BOOL CDlgLableDesign::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_LEFT:
para.point.x--;
ShowImage();
break;
case VK_RIGHT:
para.point.x++;
ShowImage();
break;
case VK_UP:
para.point.y--;
ShowImage();
break;
case VK_DOWN:
para.point.y++;
ShowImage();
break;
case VK_PRIOR:
case VK_OEM_MINUS:
case VK_SUBTRACT:
para.fontHeight--;
Log("字高:"+ CString(to_string(para.fontHeight).c_str()));
ShowImage();
break;
case VK_NEXT:
case VK_OEM_PLUS:
case VK_ADD:
para.fontHeight++;
Log("字高:" + CString(to_string(para.fontHeight).c_str()));
ShowImage();
break;
default:
break;
}
return TRUE;
}
return CDialogEx::PreTranslateMessage(pMsg);
}
void CDlgLableDesign::OnClose()
{
WritePara();
CDialogEx::OnClose();
}
#pragma once
#include "afxdialogex.h"
// CDlgLableDesign 对话框
class CDlgLableDesign : public CDialogEx
{
DECLARE_DYNAMIC(CDlgLableDesign)
public:
CDlgLableDesign(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CDlgLableDesign();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG_LabelDesign };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
afx_msg void OnBnClickedButtonPrintOutbox();
afx_msg void OnTimer(UINT_PTR nIDEvent);
// afx_msg void OnMouseMove(UINT nFlags, CPoint point);
// afx_msg void OnPaint();
public:
CEdit m_editDisplay;
void Log(CString szInfo);
BOOL CDlgLableDesign::DrawSomething(CDC* pDC, int x, int y);
void CDlgLableDesign::ShowImage();
BOOL LoadImageToPictureControl(CString pic);
// 在对话框头文件中
afx_msg void OnClickedStaticImage();
// afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnClose();
};