前言:
此时看官们对“对话框和窗口的作用是一样的吗”都比较关注,姐妹们都需要了解一些“对话框和窗口的作用是一样的吗”的相关内容。那么小编在网摘上收集了一些有关“对话框和窗口的作用是一样的吗””的相关资讯,希望朋友们能喜欢,兄弟们快快来学习一下吧!开篇预告
前段时间,我在其他平台发布了一篇介绍“轻松玩转windows控制台”的文章,被不少粉丝私信批评,甚至还有个别言辞激烈的。
是因为文章写的不好吗?应该不是,因为两天时间就突破了90多个收藏,说明大家还是挺喜欢这种实用的、技巧性的技术文章,但是为什么还是被批评呢?
因为文章通篇以代码为主,虽然功能很多,但并没有详细的解释,导致大家在用的时候,有很多地方出现问题。
基于此,我决定围绕“轻松玩转windwos控制台”主题,写一个系列性的文章,通过详细介绍控制台方面的各种操作技巧,从而提高c语言初学者的学习兴趣。
我大致的规划主要分为这几块:
第一个系列是对控制台的各种“魔改”,包括标题修改、输出文字的字体大小、字体样式、文字颜色、屏幕背景颜色、控制台窗口的移动、居中显示、窗口大小、以及文字在窗口内任意位置的显示、中文字符的正确显示等等。
这个系列看完之后,就开始发布控制台窗口的图形化操作的系列文章。
比如控制台如何控制鼠标、键盘,如何将屏幕背景改成彩色图片,如何在控制台内实现动画效果等等。为后面第三个系列控制台图形游戏开发打下基础。
第三个系列我准备围绕一个游戏的一步步实现来发布文章,可以是一个超级玛丽游戏,或者一个台球游戏都可以,游戏本身我早就已经调测运行。
话不多说,开始我们的第一个“玩转之旅”。
控制台介绍
本段是控制台的基础介绍,大家不感兴趣,可以直接跳过,也不影响后面阅读。
我们用c语言刚刚编写程序时,一般都是会在屏幕上弹出一个黑乎乎的窗口,然后黑底白字的显示一行行内容。这个黑乎乎的窗口界面,我们一般称为“控制台”,英文是Console,而在控制台界面内运行的程序,我们一般称为“控制台程序”。
我们把通过控制台运行程序的方式,称为CUI,即Command User Interface,命令用户界面。相对应的,还有一种图形化用户界面,GUI,即Graphics User Interface。有时候,我们也把CUI模式称为CLI模式,即Command Line Interface ,命令行界面,都可以。
我们一般通过执行cmd.exe命令进入控制台窗口,从而运行控制台程序。
以上这些都是最基础的概念,后面文章中用到什么就介绍什么,尽量降低复杂度。
控制台标题(Console Ttile)
我们先从控制台标题入手。
控制台程序启动时,窗口上方会有一个title(标题)。这个title显示的是程的绝对路径和程序名称。这个title字符串我们称为“原始的窗口标题名称”,即original title。如图:
这个字符串显示的真的很丑,我们一般都会改成我们喜欢的内容,如下所示:
围绕控制台窗口的标题,可以实现三个功能。分别是“修改控制台标题”、“获取控制台标题”、“获取原始控制台标题”。控制台标题被我们修改以后,有时候我们可能需要知道程序所在的绝对路径和程序名称,通过“获取原始控制台标题”这个功能就很方便。下面来看一下这3个功能对应的函数如何使用的, 并简单的介绍下windows的win32API调用。
注释:如果对Win32API不感兴趣,可以直接复制代码使用即可。
功能:修改控制台标题
若修改控制台当前标题,需要用到的函数原型如下:
BOOL SetConsoleTitle(LPCTSTR lpConsoleTitle);
在学习如何使用这个函数时,我们先介绍一下一些windos程序设计的基本概念,以便于后面能熟练的使用各种控制台函数。
对初学者而言,使用windows的API函数,应该会有段很痛苦的适应过程。因为微软把c/c++的基本数据类型和自定义数据类型,都采用了匈牙利命名法进行了封装,我本人对这个命名法是非常厌恶的,但是还是要学习下。[狗头]
函数名: SetConsoleTitle,设置当前控制台标题。参数类型:LPCTSTR,这是微软开发团队自定义的数据类型,我们来分析下。
L表示long类型,用来表示长整型数据;P是pointer,表示指针类型;LP表示长整型指针(即32位或64位指针类型,取决于系统是32位或64位);C表示const,LPC表示这个指针类型指向的数据是常量数据;T是type,用来表示通用类型的含义(泛型),表示有unicode版本,或者ANSI版本,暂时不用理会;STR是字符串string的含义。
下面我列个表,就看的比较清爽了。
L:long类型P:pointer,指针类型LP:长整型指针C:constLPC:指针指向常量T:type,泛型(暂时忽略)STR:string,字符串LPCTSTR:LP + C + (T) + STR
由此可知,LPCTSTR,就是一个指向字符串常量的指针(字符串本身就是常量数据),可以近似理解成c语言中的const char*。
返回值:BOOL
BOOL,就是布尔类型,其实就是一个int类型:
typedef int BOOL;
如果真,就是TRUE,假就是FALSE。其实TRUE就是1,FALSE就是0。
本函数的参数是输入型参数(什么是输入型参数和输出型参数,可以查看我的这篇文章:c语言解剖课:函数的输入参数和输出参数)
这个参数在使用之前,其所在的外部变量是一个字符指针类型,必须被初始化,并且已经存放了新的标题字符串,字符个数必须小于 64K(等于64*1024个字节,谁能用这么多?)当函数执行成功,当前标题修改成新的字符串时,就返回为TRUE,执行失败就返回FALSE。
我们来写一个演示代码:
#include <stdio.h>#include <windows.h>int main() { LPCSTR newStr = "hello,title!" ; if(SetConsoleTitle(newStr) == TRUE){ printf("Title is changed!\n"); } system("pause"); return 0;}
首先,文件的后缀需要是.cpp或其他C++源文件的格式,而不能是.c的后缀了。
其次,需要包含windows.h头文件,因为对控制台操作的函数,都是这个头文件提供的。我们需要先定义一个字符串,存放新的标题。
当然,你也可以用 char* 来定义,但是建议最好和windows编程风格保持一致,就用这个非常别扭的 LPCSTR类型,然后判断是否设置成功。
随后的System函数,参数是一个字符串,这个字符串实际上就是一个DOS命令,这里是一个暂停命令。如果没有这条语句,运行这个程序时,屏幕会一闪而过。运行效果如图:
窗口中的“请按任意键继续...”,就是system("pause");这行代码中的pause暂停命令起的作用。当然,为了简洁,你也可以直接写成如下形式:
#include <stdio.h>#include <windows.h>int main() { SetConsoleTitle("hello,title!"); system("pause"); return 0;}
但是,最好不要这么写,因为随着功能越来越强大(复杂),会很不利于维护。那么我们想显示中文行不行?我们先测试一下,请看下面这段代码:
#include <windows.h>int main() { SetConsoleTitle("你好世界"); system("pause"); return 0;}
看一下执行的效果,如图:
控制台标题输出的是乱码,当然,有可能你的编译器运行后,输出的是中文。没关系,继续往下看就好了。为什么会这样?不用急。我们右击标题栏,点“属性”进去,注意看,下面这个截图中的红框,显示了系统当前使用的编码。
代码页,即Code Page,简写为CP,表明了当前控制台的编码情况。如果是437,则是美国英语;如果是936,则是ANSI/OEM - 简体中文默认的GBK编码;如果是950 ,则是繁体中文;如果是65001,则是UTF-8编码。当然,代码页有很多种,我们只需要关心一个就可以了,就是UTF-8编码。用列表显示代码页标识符和编码标准,会更清楚:
437 :美国英语936 : ANSI/OEM - GBK950 : 繁体中文650001 :UTF-8
如果控制台显示乱码,我们可以将当前代码页设置为65001,即UTF-8,就可以正确显示中文。注意,并不是因为当前代码页是936,所以就显示乱码。
显示乱码是编译器的编码规范和系统的编码规范不一致,需要手动修改编码规范。通过下面介绍的方法,通过修改代码页为UTF-8,可以快速解决问题,但不是唯一的解决办法。
函数SetConsoleCP是设置控制台输入字符使用的编码标准,SetConsoleOutputCP是设置控制台输出字符的编码标准,函数原型如下:
BOOL SetConsoleCP(UINT wCodePageID);BOOL SetConsoleOutputCP(UINT wCodePageID);
参数类型:UINT
微软将基本数据类型int封装成INT,约定为32位的有符号整数,取值范围是 -2147483648 到 2147483647。即:
typedef int INT;
而无符号整型unsigned int 被封装成UINT,约定为32位无符号整数,取值范围为 0 到 4294967295。即:
typedef unsigned int UINT;
参数的值就是代码页的标识符,比如要显示中文,UINT变量的值就是655001即可。
返回值是BOOL类型,前已介绍过,如果执行成功,则返回TRUE,否则返回FALSE。
举例如下:
#include <stdio.h>#include <windows.h>int main() { SetConsoleCP(65001);//控制台标题 SetConsoleOutputCP(65001);//输出内容 LPCSTR newStr = "你好世界!" ; if(SetConsoleTitle(newStr) == TRUE){ printf("标题修改成功!\n"); } system("pause"); return 0;}
我们看下执行结果:
我们通过SetConsoleOutputCP,设置了输出字符的代码页(Code Page,CP)为UTF-8,所以prinftf函数的输出内容,正常显示中文了,同样的输入字符显示中文,通过SetConsoleCP就可以了。
进一步的,我们在程序里,如果需要显示中文,我们需要知道当前代码页的数值是不是65001,如果不是,我们需要设置成6501。我们如知晓呢?
可以通过GetConsoleCP获取输入状态的代码页,GetConsoleOutputCP获取输出状态的代码页,从而进行判断。函数原型如下:
UINT GetConsoleCP(void);UINT WINAPI GetConsoleOutputCP(void);
这两个函数没有参数,返回值是UINT类型,也就是当前所用的代码页标识符。第一个函数返回的是输入模式的代码页标识符,第二个函数返回的是输出模式的代码页标识符。通过对代码页判断,然后始终保持当前代码页标识符为65001即可。
示例代码如下:
#include <stdio.h>#include <windows.h>int main(){ UINT codePage = GetConsoleOutputCP(); if(codePage != 65001){ SetConsoleCP(65001); SetConsoleOutputCP(65001); } LPCSTR newStr = "你好,世界!" ; if(SetConsoleTitle(newStr) == TRUE){ printf("标题修改成功!\n"); } return 0;}
我们现在可以随心所欲的修改窗口标题名了,并且也可以正确显示中文内容了。接下来,我们如何获取当前窗口的标题名呢?
功能:获取控制台标题
通过GetConsoleTtile函数,就可以获取道当前控制台的标题。函数原型如下:
DWORD GetConsoleTitle(LPTSTR lpConsoleTitle, DWORD nSize );
函数名: GetConsoleTitle;第一个参数类型:LPTSTR
这个参数的类型和上面介绍的SetConsoleTtitle函数的LPCTSTR类型,很相似。本质的区别在于字母C,LPCTSTR是指向常量字符串,不允许修改,属于输入性参数。而LPTSTR类型,指向的是可以被修改的一段区域,一般我们定义成一个数组,或者一段动态内存分配区域。
第二个参数类型:DWORD
windows编程规范中,把8个位(bit)当作1个字节BYTE,把2个BYTE当作1个字,即WORD,2个WORD为双字,即DOUBLE WORD,简写为DWORD。
1个DWORD类型的变量,等于4个字节,表示32 位无符号整数。 范围为 0 到十进制4294967295。其实就是c语言中的 unsigned long ,实际上也是这样定义的:
typedef unsigned long DWORD;
返回值和第二个参数一样,也是DWORD。
第一个参数是输出型参数,接受函数的返回数据。(什么是输入型参数和输出型参数,可以查看我的这篇文章:c语言解剖课:函数的输入参数和输出参数),用来存放获取的当前窗口标题字符串。
第二个参数是要显式的说明第一个参数所指向的内存区域的大小,以字符为单位。
如果函数成功,则返回值为控制台窗口标题的字符个数。如果函数失败,则返回值为零。
下面是一段演示代码:
#include <stdio.h>#include <windows.h>#include <stdlib.h>#include <malloc.h>int main(){ DWORD charactor_total = MAX_PATH; LPTSTR title = (LPTSTR)malloc(sizeof(CHAR)*MAX_PATH); DWORD n = GetConsoleTitle(title,charactor_total); printf("标题字符个数:%d\n",n); system("pause"); return 0;}
程序执行结果如图:
大家可以数一下标题的字符数,是不是91个。[憨笑]
功能:获取原始标题
当控制台窗口标题被修改后,我们有时候需要获取窗口的原始标题,也就是程序的绝对路径和程序全名(包括后缀),这非常有用,因为可以根据这个字符串提取出程序文件所在的目录。
获取原始标题的函数为GetConsoleOriginalTitle(),当窗口标题未被修改时,GetConsoleTtile()和它的功能是一样的,当被修改后,就出现了本质的差别,所以小心不要用错函数。
函数原型如下:
DWORD GetConsoleOriginalTitle( LPTSTR lpConsoleTitle, DWORD nSize);
这个函数的参数和用法,就不再讲解,和GetConsoleTitle函数类似。
总 结
今天因为是第一篇文章,特别是对windows程序设计比较陌生的读者,对微软的自定义数据结构估计也会不适应,所以本文对微软自定义的数据结构讲解的比较详细,后面文章都会对出现的数据结构进行详细讲解,感兴趣的读者可以持续关注我,感谢。
段誉,2024年2月9日(除夕),写于合肥。
标签: #对话框和窗口的作用是一样的吗 #对话框和窗口的作用是一样的吗为什么 #c语言调用函数返回值是bool怎么写 #控制台一闪