众所周知,富文本控件,RichTextControl,用来呈现文本内容的一个控件,功能上相对记事本来说更加丰富,但又不及Word。 但,我们的目标又不是开发另外一个Word。 我们可以使用EM_STREAMIN消息将整个文件加载到富文本控件,此消息接受一个IStream的数据源,并一次性地将整个文件的内容加载的控件上。听起来,是不是还不错? 如果你MSDN上阅读了关于EM_STREAMIN的更多信息,则可以很容易地理解它的基本用法,我们来看看下面的例子。 上面的代码,你可以先自行体会一下。 EM_STREAMIN消息希望告知它流的格式(SF_RTF)并提供指向控制输入的EDITSTREAM...

我经常看到一些朋友会编写类似于下面的代码。 上面的这段代码的本意是:通过对窗口树根结点进行操作,然后对每个子窗口进行操作,对窗口树中的所有窗口执行操作。反过来,对子项的操作又以递归方式执行,因此我们最终可以看到树中的每个窗口。 除了如果你真的在一个模糊有趣的窗口树上运行这个函数,你会发现项目被计算了多次。 原因是EnumChildWindows函数已经执行递归。 以下是MSDN对EnumChildWindows的描述:如果子窗口创建了自己的子窗口,则EnumChildWindows也会枚举这些窗口。 如果你添加自己的递归,那么你最终会计算两次孙窗口,四次曾孙窗口,依此类推。递归已由EnumC...

出于某种原因,人们确实对打印富文本控件中的内容感到困惑。我并非打印方面的专家,但是经过对资料的研究的,我也算弄明白了,今天在此记录一下。 解决问题的关键是这个消息:EM_FORMATRANGE。每次发送这个消息的时候,控件的内容会打印一些,然后消息会返回尚未打印的文本的首个字符的索引,然后可以依据这个索引继续传递给它,并打印下一块文本内容。剩下的工作就是简单的设置工作和资源的销毁了。 我们首先获取页面的尺寸,并使用EM_SETTARGETDEVICE消息告诉富文本控件我们打算呈现的内容。接下来,我们需要填写FORMATRANGE结构体,为此,我们指定要渲染到的HDC以及纸张尺寸。但是字符范围...

今天的问题来自我的一位读者: “如果我在命令行下启动我的程序,一切都是正常的。但是,当我在代码中调用ShellExecuteEx来启动程序时,好像什么都没有发生,这是为什么?” 在我问下面的第二个能给出答案的问题之前,你可以自己思考下大概问题的原因出在哪里? 下面是来自另外一个读者的问题反馈,它和上面这个十分类似: “我正在尝试使用ShellExecute打开一个文档。函数正常返回了(返回值大于32),但是屏幕上没有显示任何东西。我的代码如下:if(ShellExecute(Handle,NULL,FileName,NULL,NULL,NULL)<=(HINSTANCE)32)…” 第...

有些人对术语WM_USER表示消息范围基的名称有不同的意见,因为WM_USER是由窗口类的实现者来定义的。他们抱怨的是,用户不能使用它们,因为它们属于窗口类定义的一部分。 但是,问题是,”这里的用户是谁?”换句话说,当我们说”用户自定义”这个词的时候,做自定义操作的这个用户到底是指谁? 在上面这个问题中,总共有四个不同的组件涉及其中,每个组件都有它自己的消息范围。 >窗口管理器处理WM_USER之下的消息。>窗口类的实现者处理WM_USER到WM_APP–1之间的消息。>应用程序(具体来说,就是创建窗口的代码)处理WM_APP到MAXINTATOM–1之间的消息。>所...

如题,什么时候需要将一个类的方法声明为虚函数(virtual),这个问题涵盖技术和哲学两个层面。 从技术角度来说,如果你希望在运行阶段(而非编译阶段)根据对象的实际类型来调用方法时,就需要将它声明为一个虚拟函数。 但还有一个哲学层面的解释。 有些人认为,一个类的每个方法都应该是虚拟的,以便派生类可以以基类可能没有预料到的方式重写基类的行为。这确实可以提供了最大的灵活性,避免了将来必须重新设计类的风险。但我认为这种可扩展性的成本被严重低估了。 一旦你将一个方法标记为虚拟的,你的生活就会变得更加复杂。每个虚拟方法都是一个扩展点,这意味着你必须假设最坏的情况可能会发生。 例如,调用虚拟方法时不能持...

我想,有一条编程铁律已经深深的刻入到你的头脑中了:使用成套的函数来分配和释放内存,例如,如果使用LocalAlloc分配内存,则应该使用LocalFree,类似的例子还有:GlobalAlloc对应GlobalFree,new[]对应delete[]。 但这条规则还有更深层次的潜规则。 如果你提供了一个函数分配了一段内存并返回了数据,则调用者必须知道如何释放该内存。实现这个目标有很多不同的方法,其中一个是在函数的文档中显式的声明内存应该如何释放。例如,FormatMessage这个函数在文档中清楚的表达了调用者应该使用LocalFree来释放已分配的内存(如果你传递了FORMAT_MESSA...

正如标题所指出的:窗口类的属性将影响所有由该窗口类创建的窗口。这就是它为什么称之为窗口类的原因。我用这么多话来强调这一点,似乎是一件显而易见的事情,但我看到许多”解决方案”忽视了这个简单的事实。 在WNDCLASS(或WNDCLASSEX)中设置的所有属性都是窗口类属性,可以通过Get/SetClassWord/Long/LongPtr访问的属性也是如此。这意味着当你修改这些属性时,它们会影响整个窗口类。 举个例子,假设你写了下面的代码:SetClassLongPtr(hwnd,GCLP_HCURSOR,(LONG_PTR)hcurNew); 那么你不只是在修改HWND指定的窗口的光标。你正...

最近有人问我下面这个问题,我们依然可以使用之前我提到的“思维调试”来研究研究。 我们碰到了一个技术问题。当在资源管理器中双击打开文档时,资源管理器不会启动我们的应用程序。更加奇怪的是,如果我们将一个调试器挂接到资源管理器进程,并在kernel32模块的CreateProcessW处下断点,然后等待CreateProcess返回,并在调试器中继续执行,则文档可以正常打开。但是,如果我们不做任何等待,应用程序也可以正常打开,但是它不会加载文档,在这种情况下,我们得到了这样的错误信息:Windows找不到‘abc.lit’。请确保你输入了正确的文档名称,然后重试。下面是我们使用的命令行:“F:\P...

有时候我会碰到下面这个问题: 我怎么通过编程的方式知道我的程序会编译成哪个目标平台?我希望我的程序的x86版本的行为和ia64版本有所区别。有什么API可以用来调用吗? 请注意,以上问题不是问当前程序是否运行在一个64位Windows系统上。而是想知道程序是否被一个x86编译器,还是一个ia64编译器所编译。 但是,我所不能理解的是,你为什么需要一个API呢?你应该已经知道你代码编译的目标平台了,因为编写代码的人就是你啊! 在MicrosoftVisualC编译器中,已经预定义好了一些符号,用来指示目标平台。 ifdef_M_IX86 //thetargetarchitectureisx8...

有人提到这样一个问题:”一个程序最多可以注册多少个窗口类?” 问题的答案不是一个具体的数字。因为大多数用户界面对象都来自一个共享的内存池,我们称之为”桌面堆内存”。尽管我们可以计算一个最大的理论值,但是在实际的场景中,这个理论值不会达到,因为还有很多其他用户界面对象也是在这个桌面堆中。 举个例子,用户可见的菜单对象和窗口对象保存在桌面堆中,还有一些其他不可见的对象也保存在其中,例如:激活的窗口枚举,窗口的位置句柄,甚至挂接的线程输入队列等。 如果创建了过多的窗口或者菜单,则留给其他对象(例如,注册窗口类)的空间就不多了,因为所有这些用户界面对象都共享同一个内存空间。 当有人问这类问题的时候,...

关于设备上下文(DeviceContext,简称DC),我想到这样一个原则:大多数情况下,窗口DC只是作为临时使用。 例如,如果你想在窗口中绘制些什么东西,你可以在WM_PAINT消息到来的时候,调用BeginPaint,或者在其他时间点,调用GetDC,但我们通常还是建议将绘制工作尽可能地放在WM_PAINT消息处理代码中。 当你调用上面说的两个函数后,窗口管理器会产生一个窗口对应的DC并返回给你。然后,你可以使用这个DC进行绘制,当绘制结束的时候,通过调用EndPaint或者ReleaseDC,我们将DC恢复它原本的状态并返回给窗口管理器。 从内部实现的角度来看,窗口管理器保留了一小段D...

对于许多C开发人员来说,如果编译器爆出了大量的编译错误,且错误之间还没有明显的关联,这可就不好玩了。如果开发环境可以提供更容易理解的错误提示和诊断体验,则开发人员就更加容易的找到错误原因并修复它。 我曾经写了一篇文章“ConceptsErrorMessagesforHumans”,里面探索了一些新的编译错误呈现的新思路,现在,感谢许多在VisualStudio上工作的人的辛勤工作,我们有更好的体验与大家分享。 在VS2022v17.8预览版3中,如果你使用MSVC构建一个MSBuild工程,在错误列表中将会显示更加丰富的关于此错误条目的信息。 >>请移步至www.topomel....

早在VS2019v16.10版本的时候,我们就官宣了对C模块(以及几乎所有其他C20特性)的全面支持,包括MSVC编译器工具集,静态分析,智能感知和调试器等,而实现模块需要将C代码实现为一种内部的临时表示形式。 今天,我们高兴地宣布将IFCSDK开源,它是Microsoft对IFC规范的一个实现。IFC规范将C程序形式化为适合基于语义操作的数据。我们开源IFCSDK的目的是,希望加速C模块在C社区和C工具生态系统中的广泛使用和实施。 什么是IFC以及它的作用是什么? C模块接口(或头单元)源文件的一种常用编译策略是将源文件(恰好一次)转换为适合在其他源文件中重用的内部表示形式。这种中间形式通...

通常来说,我认为在设计一个函数原型的时候,应该尽量避免使用布尔类型的参数,除非函数名称能十分清楚的将这个参数的意思表达出来。 我并没有想教你做事,但是请听我细说 先举两个正面的例子,有一个API函数EnableWindow,它用来启用或禁用一个窗口。它的第二个参数是一个布尔型参数,如果此参数传入TRUE,则调用此函数会将指定的窗口启用,传入FALSE,则禁用窗口。 另外一个是ShowScrollBar的最后一个参数,它也是一个布尔型的。它的含义也十分明显,如果传入TRUE,则表明将会显示滚动条,如果传入FALSE,则会将滚动条隐藏。 这两个例子中,布尔型参数的含义都清楚的体现在了函数的名称中...

早在VS202217.5版本,MicrosoftVisualC库已经初步支持了C11atomics。今天,我们很高兴地宣布,在最新版本VS202217.8预览版2中已正式支持C11线程。开发者可以更轻松地将跨平台C应用程序移植到Windows,而无需开发线程在不同平台上的兼容性层。 和C11atomics不同的是,C11线程并不和C的 共享同一个ABI,但是C程序可以包含C11线程的头文件并像调用其他C程序那样调用该头文件中的函数。两者都是根据Windows提供的原语实现的,因此它们的用法可以在同一程序和同一线程中混合使用。但是,他们的底层实现是不同的,例如,你不能将C11互斥体与C条件变量...

今天文章的主题灵感来自客户的一个问题: 我在研究一个代码中的栈溢出问题。为了减小栈帧的大小,我尽可能多地删除了局部变量,但仍有很多栈空间无法解释。除了局部变量、参数、保存的寄存器和返回地址之外,栈上还有什么其他的东西呢? 我的回答是,嗯,还有结构化(SEH)的异常处理信息,但这通常不会占用太多栈空间,因此不会成为”大量”神秘栈使用的来源。 我的猜测是,代码正在生成大量大型C临时对象。请考虑以下程序片段: >>请移步至topomel.com以查看图片<< 有人会问了:”这段代码是如何编译的?函数Foo想要一个BigBuffer,而不是一个整数!”然而编译它确实如此。 ...

作为一名开发者,我想,你最不希望发生的事情之一是:当你调试一个Bug的时候,Bug就消失了,但直接运行的时候,Bug又出现了。 通过ifdefDEBUG技法,可以将额外的调试代码放置到程序中。毕竟,这些调试代码仅会在程序的调试版本中才会生效。但是,一定要注意的是,这些调试代码不应该修改程序的执行逻辑。 你可以在调试代码中执行参数验证,执行断言,追踪资源的使用,这可能会降低程序的性能并消耗更多的计算资源,这些都是可以接受的,唯一需要注意的一条是:不要在调试代码中修改程序的流程。 我们来看看下面的例子。 >>请移步至topomel.com以查看图片<< 上面的代码是错误的...

VSBT是VisualStudioBuildTools的缩写。从今天开始,你可以使用VSBT编译开源C项目了,重要的是,不需要购买VisualStudio的许可证,即使你正在开发的是一个商业或闭源项目,也是如此。 这次更新扩展了构建工具的用户权限,且不限制现有VisualStudio社区许可条款。如果你是一名开源软件项目贡献代码的开发人员,你可以像以前一样,继续免费使用VisualStudio和VSBT。 新许可证带来的好处 如果你是企业开发人员或正在开发任何闭源项目,则这个新许可证允许你使用VSBT来编译和构建任何C第三方开源依赖项,而无需付费的VisualStudio许可证,特别适用于当...

  z0Lr3p4aE7p5   2023年11月02日   56   0   0 Node.js开发人员c++

VisualStudio中的远程文件管理器可以用来访问远程机器上的文件和文件夹,通过VisualStudio自带的连接管理器,可以实现不离开开发环境直接访问远程系统,这确实十分方便。 自从此功能发布以来,VS开发团队努力工作,今天又为我们带来了新的功能,让我们来看看。 背景知识 若要访问远程文件资源管理器,请在通过VisualStudio中的Linux和嵌入式工作流下载后导航到”查看>远程文件资源管理器”。现在,当你打开跨平台C项目(适用于Linux的vcxproj或CMake项目,在具有远程SSH目标的CMake预设中至少有一个配置)时,它也将自动打开,如下图所示: 可以在此处查...

关注 更多

空空如也 ~ ~

粉丝 更多

空空如也 ~ ~