该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
这是第一次分享,求支持,嘻嘻。
看到了@江虾麻 的程序,之前用VC没有编译出来,现在用VS试过之后,真的非常喜欢窗口的WS_EX_LAYERED的属性,能做出许多很有趣的效果,所以今天做了个模拟时钟。
背景是桌面,时钟元素是PS的一些矢量图形。
在自己电脑上Release版本的CPU占用率大约为0.5%。
可以使用鼠标拖拽窗口(但是不是很灵敏),中键开启缩放开关,以便使用滚轮缩放时钟,双击可以退出程序,并且保存当前窗口位置。
话不多说,Show you the code.
//2018-5-12
//that boy
//#include "Button.h"
//#include "ExtensionForEasyX.h"
#include
#include
#include
const double PI = 3.1415926;
const tm& GetClockHandAngle(double &, double &, double &);
int GetClockHandAngle(const tm&,double &, double &, double &);
int DrawClock(const double &, const double &, const double &, bool ForceRecalculate = false);
int DrawClock(int x, int y, const double &, const double &, const double &, bool ForceRecalculate = false);
inline void putimage(int, int, IMAGE&, DWORD dwRop = SRCCOPY);
int ReadWinData(long&, long&, int&);
int SetWinData(long&, long&, int&);
IMAGE ClockDial;
IMAGE HandHour;
IMAGE HandMin;
IMAGE HandSec;
IMAGE NotHandHour;
IMAGE NotHandMin;
IMAGE NotHandSec;
int ClockSize = 300;
const COLORREF BackGroundColor = RGB(1, 1, 1);
const char SetFileName[] = "D:/Program Files/AnalogClock.dat";
bool operator !=(const tm&tm1, const tm&tm2);
bool LoadClockImage();
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
double AngleHour = 0, AngleMin = 0, AngleSec = 0;
MOUSEMSG Msg = { NULL };
POINT ScrPos = { 0,0 };
POINT LastPos = { 0,0 };
POINT CurrPos = { 0,0 };
const tm&CurrentTime = GetClockHandAngle(AngleHour, AngleMin, AngleSec);
tm LastTime = { NULL };
bool IsSetSize = false;
bool FreshScreen = false;
bool ResizeScreen = false;
if (ReadWinData(ScrPos.x,ScrPos.y,ClockSize)<3) {//读取数据
ClockSize = 300;
ScrPos.x = (GetSystemMetrics(SM_CXSCREEN) - ClockSize) / 2;
ScrPos.y = (GetSystemMetrics(SM_CYSCREEN) - ClockSize) / 2;
SetWinData(ScrPos.x, ScrPos.y, ClockSize);
}
LoadClockImage();//读取图像
HWND hwnd = initgraph(ClockSize, ClockSize);
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE)&(~(WS_CAPTION | WS_SYSMENU | WS_SIZEBOX)));
SetWindowLong(hwnd, GWL_EXSTYLE, (GetWindowLong(hwnd, GWL_EXSTYLE)&(~(WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME))) | WS_EX_LAYERED| WS_EX_TOOLWINDOW);
SetWindowPos(hwnd, HWND_TOPMOST, ScrPos.x, ScrPos.y, getwidth(), getheight(), SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_DRAWFRAME);
//设置透明色
SetLayeredWindowAttributes(hwnd, BackGroundColor, 0, LWA_COLORKEY);
setbkcolor(BackGroundColor);
BeginBatchDraw();
FlushMouseMsgBuffer();
while (1)
{
if (MouseHit())
{
GetCursorPos(&CurrPos);
while (MouseHit())
{
Msg = GetMouseMsg();
if (Msg.uMsg == WM_LBUTTONDBLCLK)
{
SetWinData(ScrPos.x, ScrPos.y, ClockSize);
EndBatchDraw();
closegraph();
return 0;
}
else if (Msg.uMsg == WM_LBUTTONDOWN)
{
GetCursorPos(&LastPos);
CurrPos = LastPos;
}
else if (Msg.mkLButton)
{
ScrPos.x += CurrPos.x - LastPos.x;
ScrPos.y += CurrPos.y - LastPos.y;
FreshScreen = true;
GetCursorPos(&LastPos);
}
else if (Msg.uMsg == WM_MBUTTONDOWN)//打开开关
{
IsSetSize = !IsSetSize;
}
else if (IsSetSize&&Msg.wheel != 0)//设置大小
{
ClockSize += Msg.wheel / 40;
ScrPos.x -= Msg.wheel / 80;
ScrPos.y -= Msg.wheel / 80;
ResizeScreen = true;
}
}
if (ResizeScreen)//重设窗口大小
{
Resize(NULL, ClockSize, ClockSize);//设置窗口大小
LoadClockImage();//重新读取图片
SetWindowPos(hwnd, HWND_TOPMOST, ScrPos.x, ScrPos.y, getwidth(), getheight(), SWP_SHOWWINDOW);
GetClockHandAngle(AngleHour, AngleMin, AngleSec);//获得当前指针角度
DrawClock(AngleHour, AngleMin, AngleSec, true);//强制重新生成所有旋转图像
ResizeScreen = false;
}
if (FreshScreen) {
SetWindowPos(hwnd, HWND_TOPMOST, ScrPos.x, ScrPos.y, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE);
FreshScreen = false;
}
}
GetClockHandAngle(AngleHour, AngleMin, AngleSec);
if (LastTime != CurrentTime) {//时间变化才会重绘
DrawClock(AngleHour, AngleMin, AngleSec);
LastTime = CurrentTime;
}
FlushBatchDraw();
Sleep(2);
}
//不会执行到
EndBatchDraw();
closegraph();
return 0;
}
int GetClockHandAngle(const tm&t, double &AngleHour, double &AngleMin, double &AngleSec)
{
static double PI_6 = PI / 6;
static double PI_30 = PI / 30;
AngleHour = (t.tm_hour % 12 + t.tm_min / 60.0)*PI_6;
AngleMin = (t.tm_min + t.tm_sec / 60.0)*PI_30;
AngleSec = (t.tm_sec)*PI_30;
return 0;
}
const tm& GetClockHandAngle(double &AngleHour, double &AngleMin, double &AngleSec)
{
static double PI_6 = PI / 6;
static double PI_30 = PI / 30;
static tm t;
static time_t tick;
if (tick == time(NULL))
return t;
tick = time(NULL);
localtime_s(&t,&tick);
AngleHour = (t.tm_hour % 12 + t.tm_min / 60.0)*PI_6;
AngleMin = (t.tm_min + t.tm_sec / 60.0)*PI_30;
AngleSec = (t.tm_sec)*PI_30;
return t;
}
int DrawClock(const double &AngleHour, const double &AngleMin, const double &AngleSec,bool ForceRecalculate)
{
return DrawClock(getwidth() / 2, getheight() / 2, AngleHour, AngleMin, AngleSec, ForceRecalculate);
}
int DrawClock(int x, int y, const double &AngleHour, const double &AngleMin, const double &AngleSec,bool ForceRecalculate)
{
static IMAGE handHour;
static IMAGE handMin;
static IMAGE handSec;
static IMAGE NhandHour;
static IMAGE NhandMin;
static IMAGE NhandSec;
static double Ah = 0.0, Am = 0.0, As = 0.0;
//保存所有方向指针图像太占用内存,所以实时旋转生成。
if (ForceRecalculate || Ah != AngleHour)
{
rotateimage(&handHour, &HandHour, -AngleHour, BLACK);
rotateimage(&NhandHour, &NotHandHour, -AngleHour, BLACK);
Ah = AngleHour;
}
if (ForceRecalculate || Am != AngleMin)
{
rotateimage(&handMin, &HandMin, -AngleMin, BLACK);
rotateimage(&NhandMin, &NotHandMin, -AngleMin, BLACK);
Am = AngleMin;
}
if (ForceRecalculate || As != AngleSec)
{
rotateimage(&handSec, &HandSec, -AngleSec, BLACK);
rotateimage(&NhandSec, &NotHandSec, -AngleSec, BLACK);
As = AngleSec;
}
putimage(x, y, ClockDial);
putimage(x, y, NhandHour, 0X00220326);
putimage(x, y, handHour, 0X00EE0086);
putimage(x, y, NhandMin, 0X00220326);
putimage(x, y, handMin, 0X00EE0086);
putimage(x, y, NhandSec, 0X00220326);
putimage(x, y, handSec, 0X00EE0086);
return 0;
}
inline void putimage(int x, int y, IMAGE&img, DWORD dwRop)
{
putimage(x - img.getwidth() / 2, y - img.getheight() / 2, &img, dwRop);
}
int ReadWinData(long&x, long&y, int&size)
{
FILE*fp;
fopen_s(&fp, SetFileName, "rb");
if (fp == NULL)
return -1;
int returnint = fread(&x, sizeof(x), 1, fp) + fread(&y, sizeof(x), 1, fp) + fread(&size, sizeof(x), 1, fp);
fclose(fp);
return returnint;
}
int SetWinData(long&x, long&y, int&size)
{
FILE*fp;
fopen_s(&fp, SetFileName, "wb");
if (fp == NULL)
return -1;
int returnint = fwrite(&x, sizeof(x), 1, fp) + fwrite(&y, sizeof(x), 1, fp) + fwrite(&size, sizeof(x), 1, fp);
fclose(fp);
return returnint;
}
bool LoadClockImage()
{
loadimage(&ClockDial, "IMAGE", "CLOCK", ClockSize, ClockSize,true);
loadimage(&HandHour, "IMAGE", "HandHour", ClockSize, ClockSize, true);
loadimage(&HandMin, "IMAGE", "HandMin", ClockSize, ClockSize, true);
loadimage(&HandSec, "IMAGE", "HandSec", ClockSize, ClockSize, true);
loadimage(&NotHandHour, "IMAGE", "~HandHour", ClockSize, ClockSize, true);
loadimage(&NotHandMin, "IMAGE", "~HandMin", ClockSize, ClockSize, true);
loadimage(&NotHandSec, "IMAGE", "~HandSec", ClockSize, ClockSize, true);
return true;
}
bool operator !=(const tm&tm1, const tm&tm2)//判断tm结构体不等,这里只用到了时分秒,所以不对其他成员判断。
{
return tm1.tm_sec != tm2.tm_sec
|| tm1.tm_min != tm2.tm_min
|| tm1.tm_hour != tm2.tm_hour;
}
读取资源文件的地方改成外部文件就好。透明色设为RGB(1,1,1)。