《Windows API每日一练》7.4 状态报告上使用计时器

这一节我们使用计时器,每隔一秒获取当前鼠标坐标位置的像素值,并显示在窗口,这就相当于是一个简单的取色器了。

本节必须掌握的知识点:

第47 练:取色器

7.4.1 第47练:取色器

/*------------------------------------------------------------------

047 WIN32 API 每日一练

第47个例子WHATCLR.C:使用计时器---显示了鼠标指针当前所指的热点的RGB颜色

FindWindowSize 函数---设置窗口宽和高

CreateIC函数

GetPixel函数

SetPixel函数

GetRValue宏

(c) www.bcdaren.com, 2020

----------------------------------------------------------------*/

#include <windows.h>

#define ID_TIMER 1

void FindWindowSize (int *, int *) ;

LRESULT CALLBACK WndProc (HWND , UINT , WPARAM , LPARAM ) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

PSTR szCmdLine, int iCmdShow)

{

static TCHAR szAppName[] = TEXT ("WhatClr") ;

...(略)

//获取窗口宽和高

FindWindowSize (&cxWindow, &cyWindow) ;

hwnd = CreateWindow (szAppName, TEXT ("What Color"), //创建窗口

//重叠、标题、菜单、细框

WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER ,

CW_USEDEFAULT , CW_USEDEFAULT ,

cxWindow, cyWindow,

NULL , NULL , hInstance, NULL ) ;

ShowWindow (hwnd, iCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL , 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

//设置窗口宽和高

void FindWindowSize (int * pcxWindow, int * pcyWindow)

{

HDC hdcScreen ;

TEXTMETRIC tm ;

//创建一个设备环境,返回句柄仅限用于获取系统信息

hdcScreen = CreateIC (TEXT ("DISPLAY"), NULL , NULL , NULL ) ;

//获取字体信息

GetTextMetrics (hdcScreen, &tm) ;

DeleteDC (hdcScreen) ; //删除设备对象

//窗口宽=2个边框+12个字符平均宽度

* pcxWindow = 2 * GetSystemMetrics (SM_CXBORDER ) + 12 * tm.tmAveCharWidth ;

//窗口高(2个边框+1个标题+2个字高)

* pcyWindow = 2 * GetSystemMetrics (SM_CYBORDER ) + GetSystemMetrics (SM_CYCAPTION ) +

2 * tm.tmHeight ;

}

LRESULT CALLBACK WndProc ( HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)

{

static COLORREF cr, crLast ;

static HDC hdcScreen ;

HDC hdc ;

PAINTSTRUCT ps ;

POINT pt ;

RECT rc ;

TCHAR szBuffer [16] ;

switch (message)

{

case WM_CREATE :

//创建一个信息上下文设备环境--使用显示器设备环境

hdcScreen = CreateDC (TEXT ("DISPLAY"), NULL , NULL , NULL ) ;

SetTimer (hwnd, ID_TIMER, 1000, NULL ) ; //设置计时器

return 0 ;

case WM_TIMER :

GetCursorPos (&pt) ; //获取鼠标位置信息

cr = GetPixel (hdcScreen, pt.x , pt.y ) ; //获取指定位置的GRB颜色

SetPixel (hdcScreen, pt.x , pt.y , 0) ; //指定位置设置一个黑色像素

if (cr != crLast) //如果和上次获取的颜色不同

{

crLast = cr ;

InvalidateRect (hwnd, NULL , FALSE ) ; //重绘窗口

}

return 0 ;

case WM_PAINT :

hdc = BeginPaint (hwnd, &ps) ;

GetClientRect (hwnd, &rc) ;

//获取颜色值-十六进制

wsprintf (szBuffer, TEXT (" %02X %02X %02X "),

GetRValue (cr), GetGValue (cr), GetBValue (cr)) ;

DrawText (hdc, szBuffer, -1, &rc,

DT_SINGLELINE | DT_CENTER | DT_VCENTER ) ; //显示颜色值

EndPaint (hwnd, &ps) ;

return 0 ;

case WM_DESTROY :

DeleteDC (hdcScreen) ; //删除设备

KillTimer (hwnd, ID_TIMER) ; //删除计时器

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

/******************************************************************************

CreateIC函数:创建指定装置的信息的上下文。

信息上下文提供了一种无需创建设备上下文(DC)即可快速获取有关设备信息的方法。

但是,GDI绘图功能不能接受信息上下文的句柄。

HDC CreateICA(

LPCSTR pszDriver,//指向以空字符结尾的字符串的指针,该字符串指定设备驱动程序的名称(例如,Epson)。

LPCSTR pszDevice,//指向以空字符结尾的字符串的指针,该字符串指定正在使用的特定输出设备的名称,如打印管理器

LPCSTR pszPort,//该参数将被忽略,应设置为NULL。

const DEVMODEA *pdm //指向DEVMODE结构的指针,该结构包含设备驱动程序的设备特定的初始化数据。

);

*******************************************************************************

GetPixel函数:检索在指定坐标的红,绿,蓝(RGB)颜色的像素值。

COLORREF GetPixel(

HDC hdc, //设备上下文

int x, //要检查的像素的X坐标(以逻辑单位表示)。

int y //要检查的像素的y坐标(以逻辑单位表示)。

);

*******************************************************************************

SetPixel函数:设置指定坐标的指定颜色像素。

COLORREF SetPixel(

HDC hdc, //设备上下文

int x, //要检查的像素的X坐标(以逻辑单位表示)。

int y, //要检查的像素的y坐标(以逻辑单位表示)。

COLORREF color//用于绘制点的颜色。若要创建COLORREF颜色值,请使用RGB宏。

);

*******************************************************************************

GetRValue宏:检索用于红,绿,蓝(RGB)值的红色成分的强度值。

void GetRValue(

rgb //指定RGB颜色值。

);

*/

运行结果:

图7-5 取色器

总结

实例WHATCLR.C在WinMain主程序中创建一个cxWindow宽和cyWindow高的窗口。cxWindow宽和cyWindow高是由自定义函数FindWindowSize获取的。

●FindWindowSize函数

//创建一个设备环境,返回句柄仅限用于获取系统信息,"DISPLAY"表示显示器设备

hdcScreen = CreateIC (TEXT ("DISPLAY"), NULL , NULL , NULL ) ;

//获取字体信息

GetTextMetrics (hdcScreen, &tm) ;

DeleteDC (hdcScreen) ; //删除设备对象

//窗口宽=2个边框+12个字符平均宽度

* pcxWindow = 2 * GetSystemMetrics (SM_CXBORDER ) +

12 * tm.tmAveCharWidth ;

//窗口高(2个边框+1个标题+2个字高)

* pcyWindow = 2 * GetSystemMetrics (SM_CYBORDER ) +

GetSystemMetrics (SM_CYCAPTION ) + 2 * tm.tmHeight ;

●窗口过程

处理WM_CREATE消息,调用CreateDC函数获取显示器设备"DISPLAY"的句柄。然后调用SetTimer创建一个间隔时间为1秒的计时器。

处理WM_TIMER消息,调用GetCursorPos函数获取当前鼠标位置坐标,然后调用GetPixel函数获取当前鼠标位置坐标处的像素值,并调用SetPixel函数绘制一个黑色像素点标识鼠标位置。如果当前鼠标坐标点的像素值与上次获取的像素值不同,则重绘窗口。

处理WM_PAINT消息,调用GetClientRect函数,获取当前窗口客户区矩形。然后调用DrawText函数在窗口绘制RGB颜色值。

【注意】GetPixel函数获取的像素值需要使用GetRValue宏将其分解为RGB颜色值。

处理WM_DESTROY消息时,删除屏幕设备环境句柄,销毁计时器后发送WM_QUIT消息结束。

相关推荐
何曾参静谧18 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
lulu_gh_yu1 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
hairenjing11232 小时前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机
~yY…s<#>3 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
plmm烟酒僧5 小时前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv
EricWang13585 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??5 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
希言JY5 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若5 小时前
C语言比较两个字符串是否相同
c语言
Jtti7 小时前
Windows系统服务器怎么设置远程连接?详细步骤
运维·服务器·windows