• 博客(83)
  • 收藏
  • 关注

原创 《Windows API每日一练》7.3 计时器时钟

接着绘制冒号,然后再绘制两位数字时间“分”和冒号,最后绘制两位数字时间“秒”。3.处理WM_TIMER消息,先调用SetIsotropic设置窗口参数,然后选入白色画笔,擦除原有的时针、分针和秒针,接着再选入黑色画笔,重新绘制新的时针、分针和秒针。时针每小时走30度,每分钟,分针走6度,每秒,秒针走6度。1.处理WM_CREATE消息,调用SetTimer函数创建一个计时器,并调用GetLocalTime函数获取本地时间。然后分别设置窗口和视口的原点坐标和范围,将数字显示在客户区的中心位置。

2024-07-01 06:14:58 552

原创 《Windows API每日一练》7.2 计时器的三种使用方法

这是使用计时器方法一的典型特征,通过处理WM_TIMER消息响应计时器,而不是使用计时器回调函数。实例BEEPER2.C的窗口过程在处理WM_CREATE消息时,调用SetTimer函数创建计时器的前三个参数与实例BEEPER1.C完全相同,只是最后一个参数计时器的回调函数不再是NULL,而是TimerProc。第三种设置计时器的方法与第二种方法相似,只不过SetTimer的hwnd参数被设置为 NULL,而且第二个参数(正常情况下是计时器的ID)也被忽略了。创建计时器,间隔1秒发送一次WM_TIMER。

2024-06-30 08:11:00 519

原创 《Windows API每日一练》7.1 计时器基础知识

本章提供的程序便是证明。这样,应用程序不会同时收到大量的WM_TIMER消息,尽管它可能会收到靠得很近的两个WM_TIMER消息。当计数值减到0,Windows会把一个WM_TIMER消息放到适当的应用程序的消息队列中,同时把计数值重新设置回它的原始值。由于Windows应用程序是通过正常的消息队列来接收WM_TIMER消息,所以你绝对不用担心程序在处理其他任务时会被突然而来的WM_TIMER消息所“中断”。因此,在实际应用中,如果需要更高精度的计时器,可以使用高精度计时器,并进行适当的性能测试和调优。

2024-06-29 07:04:05 652

原创 《Windows API每日一练》6.4 程序测试

前面我们讨论了鼠标的一些基础知识,本节我们将通过一些实例来讲解鼠标消息的不同处理方式。本节必须掌握的知识点: 第36练:鼠标击中测试1 第37练:鼠标击中测试2—增加键盘接口 第38练:鼠标击中测试3—子窗口 第39练:鼠标击中测试4—子窗口增加键盘接口 第40练:捕获鼠标消息1 第41练:捕获鼠标消息2 第42练:获取系统配置信息No.2—增加鼠标滚轮/*---------------------------

2024-06-28 07:02:53 827

原创 《Windows API每日一练》6.3 非客户区鼠标消息

对非客户区消息来说, DefWindowProc处理WM_NCHITTEST消息后返回一个可用于鼠标消息参数wParam的值。这些消息提供了与非客户区鼠标交互相关的信息,应用程序可以根据这些消息来处理非客户区的鼠标事件。非客户区鼠标消息是指在 Windows 操作系统中,当鼠标位于窗口的非客户区域时发送的鼠标相关的消息。如果 DefWindowProc 在处理 WM_NCHITTEST 消息之后返回 HTCLIENT,则 Windows 会将屏幕坐标转换成客户区坐标,并产生一个客户区鼠标消息。

2024-06-27 05:57:08 813

原创 《Windows API每日一练》6.2 客户区鼠标消息

●若在非活动窗口的客户区内按下鼠标左键,Windows会将该窗口变为活动窗口,并向窗口过程发送WM_LBUTTONDOWN消息。类似地,当移动鼠标到另一个窗口再释放时,前一个窗口过程在接收 WM_LBUTTONDOWN消息后,就接收不到相应的WM_LBUTTONUP消息。鼠标消息则不同:当鼠标经过窗口或在窗口内被单击,则即使该窗口是非活动窗口或不带输入焦点, 窗口过程还是会收到鼠标消息。如果想在客户区外释放鼠标,并继续设计图形,就可以在客户区外按下鼠标的左键,再将鼠标移入客户区。然后再恢复原鼠标位图。

2024-06-26 06:52:51 962

原创 《Windows API每日一练》6.1 鼠标基础知识

但是,在一个计算机培训程序中,如果想在屏幕上画出一个鼠标, 在这种情况下可能需要知道鼠标的按钮是否己被切换。箭头的顶点即为热点。这些消息是在 Windows 消息循环中使用的常见鼠标消息,你可以在应用程序的消息处理过程中捕获并响应这些消息。早期的鼠标是单键鼠标,只有一个键,后来逐步改进为双键鼠标和带滚轮的双键鼠标。当用户与鼠标进行交互时,系统会生成相应的鼠标消息,以通知应用程序有关鼠标操作的信息。在 Windows 消息循环中,可以通过检查消息的消息类型来确定是否为鼠标消息,并进一步处理相应的操作。

2024-06-25 06:33:18 752

原创 《Windows API每日一练》5.5 插入符号

正如名称所暗示的,当窗口过程接收输入焦点时,它接收到一个WM_SETFOCUS 消息:当它失去输入焦点时,收到一个WM_KILLFOCUS消息。【注意】移动字符时,先隐藏插入符,再选入新创建的逻辑字体绘制字符,绘制完成后重新显示插入符。●在WM_SIZE消息中,当窗口客户区大小发生变化时,使用空格字符清空窗口客户区,然后将插入符置于窗口客户区的左上角,然后重绘窗口。正常可见字符的处理:与Delete键的处理过程类似,先隐藏插入符,然后绘制字符后再重新显示插入符,再将插入符置于下一个位置。

2024-06-24 06:07:49 902

原创 《Windows API每日一练》5.4 键盘消息和字符集

/当前字体字符集。不需要返回,接着窗口过程处理WM_CREATE消息和WM_DISPLAYCHANGE消息,调用GetSystemMetrics函数获取当前窗口客户区的最大宽和高,然后调用CreateFont函数创建一个新的逻辑字体,并调用SelectObject函数将新创建的逻辑字体选入当前设备环境。Windows 利用TrueType字体达到了真正的所见即所得(what you see is what you get, WYSIWYG),使 得在显示器上显示的字体和打印机输出的字体是准确匹配的。

2024-06-23 07:20:27 1186

原创 《Windows API每日一练》5.3 字符消息

第一个消息的wParam参数等于音调本身的ASCII码(与传递给WM_DEADCHAR消息的 wParam参数相同),第二个消息的wParam参数等于字母’s’的ASCII码。我们按照以下的基本规则来处理击键和字符消息:如果你需要读取输入到窗口中的键 盘字符,就处理WM_CHAR消息:如果你需要读取光标键、功能键、Delete键、Insert键、 Shift键、Ctrl键和Alt键,则处理WM_KEYDOWN消息。这意味着窗口过程会接收到用ANSI字符编码的消息和用Unicode字 符编码的消息。

2024-06-22 07:19:22 1055

原创 《Windows API每日一练》5.2 按键消息

但是,如果你按下一个键不放,且窗口过程不足够快,跟不上输入速率(该项可在控制面板的【键盘】应用程序中设置)来处理击键消息,Windows就会把一些WM_KEYDOWN和 WM_SYSKEYDOWN消息合并成一个单独的消息,并相应增加重复计数字段。而如果键以前是按下的,则键的先前状态为1。如前所述,在四个按键消息中(WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN、 WM_SYSKEYUP),wParam消息参数包含了虚拟键代码,IParam消息参数包含了帮助理解击键的其他有用信息。

2024-06-21 08:23:33 1164

原创 《Windows API每日一练》5.1 键盘基础

我们在第二章2.3节消息机制中讲述过,当用户按下一个按键时,产生的按键消息会被送入到Windows系统总的消息队列,然后根据按键消息所属的窗口将其送入到对应的窗口消息队列。因为当应用程序1接收到一个特殊的、转换窗口焦点的击键动作时,后续的击键消息也应被转移到另一个程序(如应用程序2)的队列中去。如果活动窗口有子窗口,具有输入焦点的窗口可以是活动窗口,也可以是它的子孙窗口中的一个。具有输入焦点的窗口要么是活动窗口,要么是活动窗口的子孙窗口——也就是说,活动窗口的子窗口,或者是活动窗口的子窗口的子窗口,等等。

2024-06-20 06:55:45 1287

原创 《Windows API每日一练》4.6 矩形、区域和裁剪

最后,可以通过读取交集矩形的坐标,即rectIntersect的左上角和右下角的坐标,来获取两个矩形的交集位置。最后,可以通过读取偏移后的矩形坐标,即rect的左上角和右下角的坐标,来获取偏移后的矩形位置。最后,可以通过读取调整后的矩形坐标,即rect的左上角和右下角的坐标,来获取调整后的矩形尺寸。最后,可以通过读取并集矩形的坐标,即rectUnion的左上角和右下角的坐标,来获取两个矩形的并集位置。最后,可以通过读取目标矩形坐标,即rectDst的左上角和右下角的坐标,来获取复制后的矩形位置。

2024-06-19 07:04:25 549

原创 《Windows API每日一练》4.5 GDI映射模式

在大多数的映射模式下,范围是由映射方式所隐含的,不能改变。此外,因为在此映射模式下逻辑和设备坐标是一一对应的,所以在不同的设备和不同的屏幕分辨率下,相同的逻辑坐标可能会导致实际显示结果的差异。值得注意的是,设备坐标与你的实际分辨率有关,同一的设备坐标在不同的设备或设置上,显示出来的效果可能会有所不同。例如,如果你在一个高DPI(分辨率)设置的显示屏和低DPI设置的显示屏上使用相同的设备坐标,显示的内容的物理大小(例如以毫米或英寸为单位)可能会有区别,即所谓的DPI敏感或DPI无关问题。

2024-06-18 08:51:09 780

原创 《Windows API每日一练》4.4 绘制填充区域

如果背景的模式是TRANSPARENT,则Windows只画出阴影线,不填充它们之间的空隙。上述实例非常简单,窗口过程中处理WM_PAINT消息时,先调用SelectObject函数选入一个灰色背景画刷,然后使用一个for循环语句初始化一个多边形顶点坐标数组,接着调用SetPolyFillMode函数和SetPolyFillMode函数设置填充模式并绘制多边形。该规则通过画直线从需要考虑填充的区域到区域外部,如果这个线穿过路径的交叉点次数是奇数,则算作在路径内部,该区域会被填充,如果是偶数,则不会被填充。

2024-06-17 06:29:01 976

原创 《Windows API每日一练》4.3 点和线的绘制

接着,就可以使用这个新的画笔来绘制线条。需要注意的是,SetPixel函数由于每次只能修改一个像素的颜色,所以在大量绘制像素时可能会比较慢,不适合对整个图形进行绘制,或者需要高效绘制的场景。当使用非PS_INSIDEFRAME 样式的笔样式时,如果用于绘制轮廓的画笔宽度大于1个像素,那么画笔的中心会处于边界之上,这样画出的轮廓线部分将会在边框之外。但需要注意的是,这个弧是在由 nLeftRect,nTopRect,nRightRect,nBottomRect 定义的矩形框内绘制的,因此可能不是完全的圆弧。

2024-06-16 09:57:00 1151

原创 《Windows API每日一练》4.2 设备环境

如果hdc是一个屏幕设备环境的句柄,这里所获取的信息和从 GetSystemMetrics函数获取的信息是一样的。例如,当你调用 TextOut函数时,仅需要在函数中指定设备环境句柄、起始坐标、文本以及文本的长度,不需要指定字体、文本的颜色、文本背景的颜色或者字符间距。当你想改变这些属性时,可以调用函数来执行,之后调用的TextOut函数就会使用新的设备环境的属性。经常需要获取这些设备的某些信息,包括显示器的大小(以像素或者物理尺寸的方式)和它的色彩能力。但是,GDI 绘图函数不能接受信息上下文的句柄。

2024-06-15 07:29:05 885

原创 《Windows API每日一练》4.1 GDI绘图

尽管一些图形语言并不允许使用像素坐标,但是 Windows GDI允许使用任何一种坐标系统(可以使用其他依据物理测量得到的坐标系统),所以你可以使用虚拟坐标系统来保证程序与硬件独立,也可以使用设备坐标系统来完全迎合硬件的需求。◆可被填充的封闭区域。这个画刷可以是纯色的,或者是使用某种填充模式(如一系列水平的、垂直的或者倾斜的图案),还可以是在水平或垂直方向不停重复的位图图像。1.设备上下文(Device Context,DC):设备上下文是GDI的核心概念,它是一个数据结构,包含了在设备中绘图的所有信息。

2024-06-14 06:32:23 503

原创 《Windows API每日一练》3.3 更好效果的滚动条

回顾一下,在实例SYSMETS2.C中,在处理WM_CREATE消息时,我们将滚动条的滚动范围设置为0~NUMLINES – 1,实际的滚动效果是显示全部内容后,结尾存在大量的空白区域。Windows很聪明的隐藏了滚动条,只需要在调用SetScrollInfo时设定SIF_DISABLENOSCROLL,以让Windows显示一个被禁用的滚动条。SIF_POS与此类似:在调用SetScrollInfo时,须在nPos字段中指定滚动条的位置,而GetScrollInfo则在nPos中返回当前的位置。

2024-06-13 05:44:26 824

原创 3.2 窗口滚动条

如果是鼠标拖动滚动条滑块,则WM_VSCROLL消息的wParam参数的高字记录当前滑块的位置。因为指示滚动条位置的消息 WM_HSCROLL和 WM_VSCROLL限于位置数据的16位,所以对于SetScrollRange函数的 nMaxPos参数,仅依赖于这些消息来获取位置数据的应用程序的实际最大值为65,535。相应的,当滑块在滚动条的底部(或最右)时,位置是范围的最大值。在使用滚动条时,一个常见的模式是,在响应滚动条相关的Windows消息(如WM_SCROLL)时,获取和设置滚动条的位置。

2024-06-12 05:58:00 938

原创 《Windows API每日一练》3.1 绘制文本

●需要注意的是,虽然系统会自动处理无效区域的重绘,但是在某些情况下,如果不需要立即更新窗口,或者你希望在一个特定的时间(例如在一系列的更改全部完成后)再更新,可以使用ValidateRect或ValidateRgn函数来清除无效区域,避免马上触发WM_PAINT消息。比如在非等宽字体中,字符’I’的宽度要远小于字符’W’。程序应该收集并保存所有用于绘制客户区的信息,但是只在需要时才会进行绘制——当收到WM_PAINT消息时,如果程序需要在其他时候更新客户区,可以强制Windows生成WM_PAINT消息。

2024-06-11 06:14:58 771

原创 新书推荐:2.3 消息机制

SendMessage是一个Windows API函数,用于将一个消息发送到指定的窗口,并等待接收消息的窗口处理完该消息后返回。在Windows程序中,消息机制的实现是基于消息队列和消息循环的。消息循环是应用程序的主循环,在消息循环的过程中,应用程序从消息队列中取出消息并进行处理。总结一下,窗口消息队列是用于存储消息的缓冲区,当操作系统有消息需要传递给应用程序时,会将消息放入消息队列中。然后,在应用程序的消息循环中,通过处理该消息的程序会根据消息中的窗口句柄,将消息分发给对应的窗口进行处理。

2024-06-10 07:06:51 1033

原创 《Windows API每日一练》

不同消息的wParam参数和lParam 参数的含义是不同的。当用户按下键盘按键(字符键),会产生一个WM_KEYDOWN消息,并送入窗口消息队列,由主程序的消息循环GetMessage函数获取,然后经过TranslateMessage函数将WM_KEYDOWN消息中的虚拟键码转换为字符,并生成一个WM_CHAR消息送入消息队列。3.本例WM_SIZE消息中调用了InvalidateRect函数,用于将指定的窗口或窗口的一部分标记为无效,并发送一个绘图消息给窗口,以便在下一次更新时重新绘制该区域。

2024-06-09 08:03:36 667

原创 新书推荐:2.2.4 第11练:消息循环

流程:用户通过点击关闭程序按钮后,消息队列增加一条消息WM_CLOSE,然后程序从消息队列中取走WM_CLOSE,WM_CLOSE消息的默认处理方式为调用DestroyWindow()向窗口发送一个WM_DESTROY消息,消息队列增加WM_DESTROY,主程序消息循环再次取出后交给Windows系统,Windows系统调用窗口过程处理WM_DESTROY消息,处理方式为调用ostQuitMessage(),在消息队列中添加WM_QUIT标记,消息循环获取WM_QUIT后退出消息循环,程序退出。

2024-06-08 07:11:35 1260

原创 2.2 窗口的创建

道理是相同的,如果该窗口类只创建了一个窗口,绑定菜单可以在初始化窗口类时进行,也可以在调用CreateWindow时进行。创建窗口完成(只存在于内存中),系统会发送第一条消息WM_CREATE,注意此时,程序并未执行到消息循环处,操作系统绕过应用程序的消息队列,直接将WM_CREATE消息发送给窗口过程。个参数:为MSG结构体的前4个成员变量 ******************************************************************************/

2024-06-07 06:06:49 1031

原创 2.1 初识Windows程序

Windows操作系统中有很多很多消息,这些消息可以是键盘消息、鼠标消息、滚动条消息、字符消息、绘图消息、控件消息、菜单消息或者是系统消息等等。当然,命名规范并不代表着编程规范,仅仅是编程规范的一部分而已,除去命名规范,还有很多编程上的细节是必须关注的,例如,等号两边留空格还是等号对齐?诸如此类,还有很多,无法一下子全部掌握并应用,但是在编程经验增加的过程中,一定也要不断的留意,自己所在的公司部门使用的是什么样的规范,并不提倡大家练就自己的规范,一定要去融入工作环境的需求。什么样的消息属于队列消息呢?

2024-06-06 07:34:57 1088

原创 1.4 Unicode简介

其实是通过相关的API函数实现的。Unicode 统一了所有字符的编码,是一个 Character Set,也就是字符集,字符集只是给所有的字符一个唯一编号,但是却没有规定如何存储,一个编号为 65 的字符,只需要一个字节就可以存下,但是编号40657的字符需要两个字节的空间才可以装下,而更靠后的字符可能会需要三个甚至四个字节的空间。对于单字节字符,只占用一个字节,实现了向下兼容 ASCII,并且能和 UTF-32 一样,包含 Unicode 中的所有字符,又能有效减少存储传输过程中占用的空间。

2024-06-04 06:46:28 984

原创 新书推荐:1.3 内存管理模式

早期的32位计算机的物理内存很小,可能只有512KB,后来随之集成电路的发展,物理内存逐渐扩大到1GB、2GB、4GB、8GB,今天32GB的物理内存已经是比较常用的了。每个进程在初始化时都会创建一个CR3(准确的说是一个CR3的值,CR3本身是个寄存器,一个核,只有一套寄存器), CR3指向一个物理页就是页目录表,一共1024个表项(也就是1024个页表),每一项32位,共4096字节(4KB)。在这种模式下,CPU的寄存器的宽度为16位,因此C语言的int数据类型的宽度也是16位。

2024-06-04 06:43:38 1261

原创 新书推荐:1.2 动态链接库与API

源程序中可以调用这些第三方功能函数,当编译器编译时,暂时将这些第三方功能函数的地址空下,待链接器链接时,在LIB库中查找对应的OBJ功能模块,并将其添加到源代码中,填写空下的函数地址。Windows操作系统中的进程可以包含一个或多个线程,进程是一些资源的集合,进程内的所有线程可以共享这些资源。随着应用程序的功能越来越多,所引用的库函数也变得越来越多,如果继续采用静态链接库的形式,无疑会大大增加程序的体积,基于有限的存储空间和程序加载效率的考虑,设计动态链接库的形式可以很好地解决上述问题。

2024-06-03 06:48:57 995

原创 新书推荐:11.6 调用约定

函数调用约定。

2024-06-02 08:07:29 511

原创 11.3 指针和函数

传入的是指针,但操作的是指针指向的对象进行操作,比如代码中:int* height指向的对象是&n_XiaoMing,间接的对n_XiaoMin进行操作。上述代码中,我们使用的函数是scanf_s,这是scanf函数的安全形式,scanf_s函数只有当参数是字符串时,需要再增加一个存放字符串缓冲区长度的参数,防止缓冲区大小不足时发生溢出。scanf函数是为主调函数中定义的对象保存的值,假如它只接收到变量的值,是无法进行保存的,scanf函数接收的是指针(指向对象的地址),由该。*px = *py;

2024-06-01 07:31:14 818

原创 新书推荐:9.5堆栈图解析生命周期

每个函数都有生命周期,每个变量也有自己的生命周期,局部变量的生命周期,通过画堆栈图,我们可以很明确的看出每个变量的生命周期。每个函数都有他自己的生命周期,在实验八十中,main函数有自己的生命周期,funtion函数也有自己的生命周期。main函数的生命周期是程序结束,funtion函数的生命周期是执行到return i;程序中,if/else语句块分别设置了3个while语句死循环结构,由flag全局变量的条件语句控制,全局变量编译的时候就已经确定了内存地址和宽度,并且存在于整个程序的生命周期。

2024-05-31 07:33:53 792

原创 新书推荐:9.3 函数调用

变量a和变量b存在于main函数的堆栈内,根据示例三十五的经验,如果调用函数two_swap传递的参数为变量a和变量b的副本,即值调用,那么在函数two_swap中只会修改变量a和变量b在函数two_swap栈内的副本,并不会影响main函数中变量a和变量b的值。这与我们的意图相悖。首先在int x,y;【注意】此时,函数two_swap的形参a和形参b都表示一个地址,形参a等于实参&a,形参b等于实参&b,如果要取形参a地址处的值,需要使用解运算符‘*’,*a表示取a地址处的值,*b表示取b地址处的值。

2024-05-30 06:06:36 932

原创 8.2 数组遍历访问

数组首地址arr为第0个数组元素的地址arr+0=ebp-18h,以此类推,第1个数组元素的地址为ebp-14h,第2个数组元素地址为ebp-10h,第3个数组元素地址为ebp-0Ch,第4个数组元素地址为ebp-8,分别存入1,2,3,4,5。上图很好的诠释数组是一块连续的内存空间,一旦被定义,则是不可以被改变大小的。3.当i=2时,把arr[2]的元素放入变量temp中,然后把arr[3]的值放入arr[2]中,再把变量temp的值赋值给arr[3],此时完成arr[2]与arr[3]的交换。

2024-05-29 07:24:50 833

原创 新书推荐:7.5 goto、break、continue语句

示例二十六代码分析汇编解析示例二十七代码分析汇编解析。

2024-05-29 07:20:18 888

原创 新书推荐:7.3 for语句

实验四十九中的代码将表达式2放置在循环语句块内,使用if语句判断条件,当i>10时,执行break语句,退出循环。条件表达式“i

2024-05-27 07:38:14 914

原创 新书推荐:7.1 do while语句

示例二十二代码分析汇编解析■do{语句块;}while(表达式)■●执行do循环体内的语句块;●判断while语句里的表达式,表达式为真继续下次循环,若为假则跳出循环;

2024-05-27 07:34:13 552

原创 新书推荐:6.2 else if语句

示例代码二十代码分析汇编解析■if(表达式1)statement1else if(表达式2)statement2else if(表达式3)statement3……elsestatementN解析:如果表达式1非0,则执行statement1,执行完退出语句;如果表达式2非0,则执行statement2,执行完退出语句;如果表达式3非0,则执行statement3,执行完退出语句;如果表达式4非0,则执行statement4,执行完退出语句;……

2024-05-24 07:10:50 1081

原创 新书推荐:6.1 if语句

计算机语言和人类语言类似,人类语言是为了解决人与人之间交流的问题,而计算机语言是为了解决程序员与计算机之间交流的问题。程序员编写的程序就是计算机的控制指令,控制计算机的运行。借助于编译工具,可以将各种不同的编程语言的源程序转换为计算机可以执行的机器语言。计算机程序是计算机的控制指令,控制计算机完成特定的功能。我们编写源程序的过程和建造房屋的过程类似,大致分为五个步骤。第一步:设计程序的架构,类似于房屋设计。先设计好图纸之后再进行下一步的建造工作。第二步:准备程序需要的数据,相当于建造房屋的原材料。

2024-05-24 07:03:10 1159

原创 新书推荐:5.1 逻辑运算符

示例十六代码分析汇编解析。

2024-05-22 06:55:42 1046

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除