注:163行仅仅是一个断点- -,stdafx.h里有一句#include <math.h>
// Clock.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "Clock.h"
#define MAX_LOADSTRING 100
#define ID_TIMER 1
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
POINT pt, pe;
RECT rt, re;
HWND g_hWnd;
HDC windowDC;
HDC memDC;
HBITMAP memBMP;
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitDC();
void RefreshDC();
void RlsDC();
void DrawClock();
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_CLOCK, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
InitDC();
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CLOCK));
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
// 注释:
//
// 仅当希望
// 此代码与添加到 Windows 95 中的“RegisterClassEx”
// 函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
// 这样应用程序就可以获得关联的
// “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CLOCK));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
int scrW = GetSystemMetrics(SM_CXSCREEN), scrH = GetSystemMetrics(SM_CYSCREEN);
hWnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, szWindowClass, szTitle, WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP, scrW - 150, 50, 100, 100, NULL, NULL, hInstance, NULL);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 0, LWA_COLORKEY);
g_hWnd = hWnd;
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
bool isDrag = false;
switch (message)
{
case WM_CREATE:
SetTimer(hWnd, ID_TIMER, 100, NULL);
break;
case WM_TIMER:
int p;
p = 0;
RefreshDC();
break;
case WM_LBUTTONDOWN:
SetCapture(hWnd);
GetCursorPos(&pt);
GetWindowRect(hWnd, &rt);
re.right = rt.right - rt.left;
re.bottom = rt.bottom - rt.top;
break;
case WM_MOUSEMOVE:
GetCursorPos(&pe);
if (wParam == MK_LBUTTON)
{
re.left = rt.left + (pe.x - pt.x);
re.top = rt.top + (pe.y - pt.y);
MoveWindow(hWnd, re.left, re.top, re.right, re.bottom, true);
}
break;
case WM_LBUTTONUP:
ReleaseCapture();
break;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
SendMessage(hWnd, WM_DESTROY, 0, 0);
break;
case WM_PAINT:
BitBlt(windowDC, 0, 0, 100, 100, memDC, 0, 0, SRCCOPY);
break;
case WM_DESTROY:
KillTimer(hWnd, ID_TIMER);
RlsDC();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void InitDC()
{
windowDC = GetDC(g_hWnd);
memDC = CreateCompatibleDC(windowDC);
memBMP = CreateCompatibleBitmap(windowDC, 100, 100);
SelectObject(memDC, memBMP);
BitBlt(memDC, 0, 0, 100, 100, windowDC, 0, 0, SRCCOPY);
RefreshDC();
}
void RefreshDC()
{
DrawClock();
BLENDFUNCTION bf;
bf.BlendOp = 0;
bf.BlendFlags = 0;
bf.AlphaFormat = 1;
bf.SourceConstantAlpha = 255;
RECT rtWin;
GetWindowRect(g_hWnd, &rtWin);
POINT ptWin = {rtWin.left, rtWin.top};
SIZE szWin = {100, 100};
POINT ptSrc = {0, 0};
UpdateLayeredWindow(g_hWnd, windowDC, &ptWin, &szWin, memDC, &ptSrc, 0, &bf, ULW_ALPHA);
}
void RlsDC()
{
if (!memBMP)
DeleteObject(memBMP);
if (!memDC)
DeleteDC(memDC);
if (!windowDC)
ReleaseDC(g_hWnd, windowDC);
}
void DrawClock()
{
RECT rtWin;
GetWindowRect(g_hWnd, &rtWin);
FillRect(memDC, &rtWin, (HBRUSH)GetStockObject(WHITE_BRUSH));
HPEN penBorder = CreatePen(PS_SOLID, 4, RGB(0, 0, 0));
HPEN penOld = (HPEN)SelectObject(memDC, penBorder);
HBRUSH brsCir = CreateSolidBrush(RGB(192, 192, 192));
HBRUSH brsOld = (HBRUSH)SelectObject(memDC, brsCir);
Ellipse(memDC, 1, 1, 99, 99);
SelectObject(memDC, penOld);
DeleteObject(penBorder);
SelectObject(memDC, brsOld);
DeleteObject(brsCir);
double dx, dy;
const double pi = atan(1.0) * 4;
for (int i = 0; i < 12; i++)
{
dx = 50 * sin((double)i / 12 * 2 * pi); dy = 50 * cos((double)i / 12 * 2 * pi);
MoveToEx(memDC, (int)(50 + dx), (int)(50 - dy), NULL);
dx = 38 * sin((double)i / 12 * 2 * pi); dy = 38 * cos((double)i / 12 * 2 * pi);
LineTo(memDC, (int)(50 + dx), (int)(50 - dy));
}
SYSTEMTIME time;
GetLocalTime(&time);
int hour = time.wHour, minute = time.wMinute, second = time.wSecond;
HPEN penHour = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
penOld = (HPEN)SelectObject(memDC, penHour);
MoveToEx(memDC, 50, 50, NULL);
dx = 22 * sin((hour % 12 + (double)minute / 60 + (double)second / 3600) / 12 * 2 * pi); dy = 22 * cos((hour % 12 + (double)minute / 60 + (double)second / 3600) / 12 * 2 * pi);
LineTo(memDC, (int)(50 + dx), (int)(50 - dy));
SelectObject(memDC, penOld);
DeleteObject(penHour);
HPEN penMinute = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
penOld = (HPEN)SelectObject(memDC, penMinute);
MoveToEx(memDC, 50, 50, NULL);
dx = 32 * sin((minute + (double)second / 60) / 60 * 2 * pi); dy = 32 * cos((minute + (double)second / 60) / 60 * 2 * pi);
LineTo(memDC, (int)(50 + dx), (int)(50 - dy));
SelectObject(memDC, penOld);
DeleteObject(penMinute);
HPEN penSecond = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
penOld = (HPEN)SelectObject(memDC, penSecond);
MoveToEx(memDC, 50, 50, NULL);
dx = 42 * sin((double)second / 60 * 2 * pi); dy = 42 * cos((double)second / 60 * 2 * pi);
LineTo(memDC, (int)(50 + dx), (int)(50 - dy));
SelectObject(memDC, penOld);
DeleteObject(penSecond);
}
6 个解决方案
#1
WM_TIMER 响应函数中设置个断点, 看看有没有执行到这里
#2
163行设置了,没有执行- -
#3
你的 WM_PAINT 中没有 BeginPaint 和 EndPaint ,因此WM_PAINT 消息再被反复触发,
只要消息队列中有消息, WM_TIMER 就不会被派送
干脆 直接在WM_PAINT 中调用 DrawClock
DrawClock();
BitBlt(windowDC, 0, 0, 100, 100, memDC, 0, 0, SRCCOPY);
只要消息队列中有消息, WM_TIMER 就不会被派送
干脆 直接在WM_PAINT 中调用 DrawClock
DrawClock();
BitBlt(windowDC, 0, 0, 100, 100, memDC, 0, 0, SRCCOPY);
#4
case WM_CREATE:
SetTimer(hWnd, ID_TIMER, 100, aaa);
break;
LPVoid* aaa()
{
;
}
SetTimer(hWnd, ID_TIMER, 100, aaa);
break;
LPVoid* aaa()
{
;
}
#5
搞定了~另外DrawClock语句必须在WM_TIMER中,如果在WM_PAINT中则并不能随时绘制。
#6
版主您好!
关于winapi的调用我是新手,我有个问题.
为啥要把句柄、设备环境弄为全局变量?我看书上都是局部。
关于winapi的调用我是新手,我有个问题.
为啥要把句柄、设备环境弄为全局变量?我看书上都是局部。
#1
WM_TIMER 响应函数中设置个断点, 看看有没有执行到这里
#2
163行设置了,没有执行- -
#3
你的 WM_PAINT 中没有 BeginPaint 和 EndPaint ,因此WM_PAINT 消息再被反复触发,
只要消息队列中有消息, WM_TIMER 就不会被派送
干脆 直接在WM_PAINT 中调用 DrawClock
DrawClock();
BitBlt(windowDC, 0, 0, 100, 100, memDC, 0, 0, SRCCOPY);
只要消息队列中有消息, WM_TIMER 就不会被派送
干脆 直接在WM_PAINT 中调用 DrawClock
DrawClock();
BitBlt(windowDC, 0, 0, 100, 100, memDC, 0, 0, SRCCOPY);
#4
case WM_CREATE:
SetTimer(hWnd, ID_TIMER, 100, aaa);
break;
LPVoid* aaa()
{
;
}
SetTimer(hWnd, ID_TIMER, 100, aaa);
break;
LPVoid* aaa()
{
;
}
#5
搞定了~另外DrawClock语句必须在WM_TIMER中,如果在WM_PAINT中则并不能随时绘制。
#6
版主您好!
关于winapi的调用我是新手,我有个问题.
为啥要把句柄、设备环境弄为全局变量?我看书上都是局部。
关于winapi的调用我是新手,我有个问题.
为啥要把句柄、设备环境弄为全局变量?我看书上都是局部。