📄 ledemuwnd.cpp
字号:
}
int ScreenStaSave = ScreenSta;
if(AccY < -30)
{
ScreenSta = 2;//左横屏
}
else if(AccY > 30)
{
ScreenSta = 3;//右横屏
}
// if(AccX < - 30)
// {
// ScreenSta = 0;//正常屏
// }
// else if(AccX > 30)
// {
// ScreenSta = 1;//反向屏
// }
if(ScreenStaSave != ScreenSta)
{
if(AutoPause && Pause)
{
AutoPause = 0;
Pause = 0;
}
}
if(ScrollSize != 0 && !Pause)//如果需要卷动的长度为0...不处理
{
//挨个将虚拟LED缓冲中的数据拷贝到实际显示缓冲中
//如果相同则不置刷新标志
CopyVirtruaLed2DisBuf();
ScrollPos++;
ScrollPos %= (ScrollSize-LedSizeX);
// ScrollPos = 0;
Invalidate();
}
if(GetTickCount() - TimeSave > 8000)
{
HANDLE hd = SetPowerRequirement(L"BKL1:",D1,POWER_NAME,NULL,0);
SystemIdleTimerReset();//10秒内必须重新调用一次
SetSystemPowerState(NULL,POWER_STATE_ON,POWER_FORCE);
ReleasePowerRequirement(hd);
TimeSave = GetTickCount();
}
break;
}
return TRUE;
break;
}
return CMzWndEx::MzDefWndProc(message,wParam,lParam);
}
//由Text创建虚拟LED数据缓冲(cVirtualLedDotBuf)
void CLedEmuWnd::LoadVirtualLedFromText(wchar_t *sDis)
{
RECT tstRect;
int i;
HDC tmpDC;
HBITMAP tmpBmp;
tmpDC = CreateCompatibleDC(GetDC(m_hWnd));
HPEN hpenBlack,hpenOld;
HBRUSH hbrushBlack,hbrushOld;
//这儿为什么使用这种笨方法,是因为这样可以关闭ClearType,否则会出现问题
//因为ClearType会出现中间色。
LOGFONT logFont =
{
20,0,0,
0, FW_BOLD,
FALSE, FALSE, 0, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
DEFAULT_PITCH | FF_SWISS, L"楷体"
};
// tmpBmp = CreateCompatibleBitmap(GetDC(m_hWnd),tstRect.right,tstRect.bottom);
logFont.lfHeight = 10;
HFONT font1= CreateFontIndirect(&logFont);//不使用FontHelper,因为要关闭ClearType;
HFONT hFontOld = (HFONT)::SelectObject(tmpDC, font1);
//用GDI函数测试最合适的字体大小
for(i = LedSizeY-5;i < LedSizeY+5;i++)
{
tstRect.left = 0;
tstRect.top = 0;
tstRect.right = 0;
tstRect.bottom = 0;
logFont.lfHeight = i;
DeleteObject((HGDIOBJ)(font1));
font1= CreateFontIndirect(&logFont);//不使用FontHelper,因为要关闭ClearType;
SelectObject(tmpDC, font1);
DrawText(tmpDC,sDis,wcslen(sDis),&tstRect,DT_CALCRECT|DT_TOP|DT_LEFT);
if(tstRect.bottom == 0)//全是空格,加载失败
{
//字串出错,也暂停
//因为图片功能是后面加的,所以出错处理不统一
Pause = TRUE;
if(cVirtualLedDotBuf != NULL)
{
delete [] cVirtualLedDotBuf;
}
return;
}
if(tstRect.bottom > LedSizeY)
break;
}
if(tstRect.bottom > LedSizeY+1)//如果字体大了点
{
i--;
logFont.lfHeight = i;
DeleteObject((HGDIOBJ)(font1));
font1= CreateFontIndirect(&logFont);//不使用FontHelper,因为要关闭ClearType;
SelectObject(tmpDC, font1);
tstRect.left = 0;
tstRect.top = 0;
tstRect.right = 0;
tstRect.bottom = 0;
DrawText(tmpDC,sDis,wcslen(sDis),&tstRect,DT_CALCRECT|DT_TOP|DT_LEFT);
}
if(tstRect.bottom > LedSizeY+1)//这儿有个细节问题,就是一个点的差距
tstRect.bottom = LedSizeY+1;
//在有效数据两边各创建一个屏幕长的空白
tstRect.right+=LedSizeX*2;
tstRect.left+=LedSizeX;
//创建BMP
tmpBmp = CreateCompatibleBitmap(GetDC(m_hWnd),tstRect.right,tstRect.bottom);
SelectObject(tmpDC, (HGDIOBJ)(tmpBmp));
//背景画黑(图片也应该类似处理才安全,偷懒了)
hpenBlack = CreatePen(PS_SOLID, 1,RGB(0, 0, 0));
hbrushBlack = CreateSolidBrush(RGB(0, 0, 0));
hpenOld=(HPEN)GetCurrentObject(tmpDC,OBJ_PEN);
hbrushOld=(HBRUSH)GetCurrentObject(tmpDC,OBJ_BRUSH);
SelectObject(tmpDC, (HGDIOBJ)hpenBlack);
SelectObject(tmpDC, (HGDIOBJ)hbrushBlack);
Rectangle(tmpDC,tstRect.left,tstRect.top,tstRect.right,tstRect.bottom);
//绘制文字
SetTextColor(tmpDC,AllColors[Color]);
SetBkMode(tmpDC,TRANSPARENT);
DrawText(tmpDC,sDis,wcslen(sDis),&tstRect,DT_TOP|DT_LEFT);
GetDCPixel2LedBuf(tmpDC,tstRect.right,tstRect.bottom);
(HFONT)::SelectObject(tmpDC, hFontOld);
SelectObject(tmpDC, (HGDIOBJ)hpenOld);
SelectObject(tmpDC, (HGDIOBJ)hbrushOld);
DeleteObject(hpenBlack);
DeleteObject(hbrushBlack);
DeleteObject((HGDIOBJ)(tmpBmp));
DeleteDC(tmpDC);
DeleteObject((HGDIOBJ)(font1));
}
//由图片创建虚拟LED数据缓冲(cVirtualLedDotBuf)
void CLedEmuWnd::LoadVirtualLedFromBmp(wchar_t *BmpName)
{
int i;
HDC tmpDC;
HBITMAP tmpBmp;
BOOL Error=FALSE;
ImagingHelper pDotImg;
if(pDotImg.LoadImage(BmpName,false,true,false))
{
//图片高度*点的宽度 必须等于 屏幕宽度(480)
for(DotSizeSelect = 0;DotSizeSelect < 3;DotSizeSelect++)
{
if(SaveLedSize[DotSizeSelect]* pDotImg.GetImageHeight() == GetWidth())
break;
}
if(DotSizeSelect == 3)
{
Error = TRUE;
MzMessageBoxEx(m_hWnd,L"图片高度错误", L"错误", MB_OK);
}
if(!Error)
{
LedSizeX = (GetHeight())/(SaveLedSize[DotSizeSelect]);
LedSizeY = (GetWidth())/(SaveLedSize[DotSizeSelect]);
RECT rcImg;
rcImg.left = 0;
rcImg.top = 0;
rcImg.right = pDotImg.GetImageWidth();
rcImg.bottom = pDotImg.GetImageHeight();
rcImg.right+=LedSizeX*2;
rcImg.left+=LedSizeX;
//创建内存DC和内存BMP
tmpDC = CreateCompatibleDC(GetDC(m_hWnd));
tmpBmp = CreateCompatibleBitmap(GetDC(m_hWnd),rcImg.right,rcImg.bottom );
SelectObject(tmpDC, (HGDIOBJ)(tmpBmp));
rcImg.right -= LedSizeX;
pDotImg.Draw(tmpDC,&rcImg);//将图片绘制到保存点图片的内部DC上
rcImg.right += LedSizeX;
if(cLedDotBuf != NULL)
delete [] cLedDotBuf;
cLedDotBuf = new UCHAR[LedSizeX*LedSizeY];
for(i = 0;i < LedSizeX*LedSizeY;i++)
{
cLedDotBuf[i]=0x80;//清除所有显示
}
//将图片缓冲到LED缓冲区
GetDCPixel2LedBuf(tmpDC,rcImg.right,rcImg.bottom);
DeleteObject((HGDIOBJ)(tmpBmp));
DeleteDC(tmpDC);
}
}
else
{
Error = TRUE;
}
if(Error)
{
if(cLedDotBuf != NULL)
delete [] cLedDotBuf;
DotSizeSelect = 0;
LedSizeX = (GetHeight())/(SaveLedSize[DotSizeSelect]);
LedSizeY = (GetWidth())/(SaveLedSize[DotSizeSelect]);
cLedDotBuf = new UCHAR[LedSizeX*LedSizeY];
for(i = 0;i < LedSizeX*LedSizeY;i++)
{
cLedDotBuf[i]=0x80;//清除所有显示
}
if(cVirtualLedDotBuf != NULL)
{
delete [] cVirtualLedDotBuf;
}
cVirtualLedDotBuf = NULL;
Pause = TRUE;//不能刷新屏幕
MzMessageBoxEx(m_hWnd,L"打开图片错误", L"错误", MB_OK);
}
}
//由HDC创建虚拟LED数据缓冲(cVirtualLedDotBuf)
//为上面两个函数服务,上面两个函数只是创建一个HDC,将此HDC和大小调用此函数就OK了
void CLedEmuWnd::GetDCPixel2LedBuf(HDC srcDC,int SizeX,int SizeY)
{
COLORREF color;
int i;
if(cVirtualLedDotBuf != NULL)
{
delete [] cVirtualLedDotBuf;
}
cVirtualLedDotBuf = new UCHAR[SizeX*SizeY];
int x,y;
for(x = 0;x < SizeX;x++)
{
for(y = 0;y < SizeY;y++)
{
color = GetPixel(srcDC,x,y);
//color = 1;
if(color != 0)
{
//对取到的颜色进行计算,转换为支持的颜色
int red = color & 0xff;
int green = (color>>8) & 0xff;
int blue = (color>>16) & 0xff;
//得到亮度最高的那个分量
i = red;
if(green > i)
{
i = green;
}
if(blue > i)
{
i = blue;
}
//简单转换到支持的颜色
int index = 0;
if(red*3 > i*2)
{
index|=0x1;
}
if(green*3 > i*2)
{
index|=0x2;
}
if(blue*3 > i*2)
{
index|=0x4;
}
//index中的.0 .1 .2位
// B G R
// 0 0 0 //底色 - 在这儿不可能存在
// 0 0 1 //红色
// 0 1 0 //绿色
// 0 1 1 //黄色
// 1 0 0 //蓝色
// 1 0 1 //紫色
// 1 1 0 //青色
// 1 1 1 //白色
int depth = i >> 5;
if(depth == 0)
{
cVirtualLedDotBuf[y*SizeX+x]=0;
}
else
{
UCHAR index2color[] = {0,0,1,2,3,4,5,6};
cVirtualLedDotBuf[y*SizeX+x] = depth+(index2color[index]<<3);
}
}
else
{
cVirtualLedDotBuf[y*SizeX+x]=0;
}
}
}
for(i = 0;i < LedSizeX*LedSizeY;i++)
{
cLedDotBuf[i]=0x80;//清除所有显示
}
ScrollSize = SizeX;
ScrollPos = 0;//一开始要显示空白
CopyVirtruaLed2DisBuf();
ScreenSta = 0;//竖屏
Pause = TRUE;//暂停
AutoPause = TRUE;//自动暂停
Invalidate();//刷新
}
//从完整虚拟LED缓冲区cVirtualLedDotBuf拷贝到cLedDotBuf(显示缓冲)
void CLedEmuWnd::CopyVirtruaLed2DisBuf()
{
int x,y;
UCHAR *pTarget;
UCHAR *pSource;
//有一个空指针就不能继续
if(cVirtualLedDotBuf == NULL || cLedDotBuf == NULL)
return;
switch(ScreenSta)
{
case 1:
case 3:
for(y = 0;y < LedSizeY;y++)
{
pTarget = cLedDotBuf+y*LedSizeX;
pSource = cVirtualLedDotBuf+y*ScrollSize+ScrollPos;
for(x = 0;x < LedSizeX;x++)
{
if(*pTarget & 0x80)//点未刷新
{
*pTarget = *pSource|0x80;//直接置为新点
}
else
{
if(((*pTarget & 0x7) == 0) && ((*pSource & 0x7) == 0))
{
//都为黑点,不需要刷新
}
else if(*pTarget == *pSource)
{
//相同点,不需要刷新
}
else
{
*pTarget = *pSource|0x80;//需要刷新
}
}
pTarget++;
pSource++;
}
}
break;
case 0:
case 2:
for(y = 0;y < LedSizeY;y++)
{
pTarget = cLedDotBuf+(LedSizeX*(LedSizeY-y))-1;
pSource = cVirtualLedDotBuf+y*ScrollSize+ScrollPos;
for(x = 0;x < LedSizeX;x++)
{
if(*pTarget & 0x80)//点未刷新
{
*pTarget = *pSource|0x80;//直接置为新点
}
else
{
if(((*pTarget & 0x7) == 0) && ((*pSource & 0x7) == 0))
{
//都为黑点,不需要刷新
}
else if(*pTarget == *pSource)
{
//相同点,不需要刷新
}
else
{
*pTarget = *pSource|0x80;//需要刷新
}
}
pTarget--;
pSource++;
}
}
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -