1.前言
如果你学过HTML,你肯定知道如何写一个超链接,像这样
<a href="http://www.baidu.com/">balabala</a>
点开就能进入链接的网站:
—> balabala
那么C++有没有这样的功能呢?貌似没有…
那么我们就这样放弃了吗?
NO!no!no!no!no!
既然没有,我们就来创造一个。
2.超链接的制作
编译系统:Dev-C++上编译通过
操作系统:Windows10
首先我们先来看一看超链接是怎样构成的
- 超链接的名称
- 链接的地址
- 链接下的下划线(可有可无)
- 访问过的链接是紫色的,没有访问过的是蓝色的
完成,现在我们开始写一些初始代码吧:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/stdc++.h>
using namespace std;
#define key_down(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)//检测按键按下
HWND hwnd=GetForegroundWindow(); //控制台窗口句柄
void gotoxy(int x, int y) { //设置光标位置(行,列)
COORD pos = {y,x};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
POINT mouse_pos() { //鼠标位置(行,列)
CONSOLE_FONT_INFO consoleCurrentFont;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
POINT p;
GetCursorPos(&p);
ScreenToClient(hwnd,&p); //获取鼠标在窗口上的位置
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
int x=p.x/=consoleCurrentFont.dwFontSize.X;
int y=p.y/=consoleCurrentFont.dwFontSize.Y;
p={y,x};
return p;
}
bool press(int x1,int y1,int x2,int y2) { //鼠标是否在矩形区域内
POINT p;
p=mouse_pos();
if(p.x>=x1&&p.x<=x2&&p.y>=y1&&p.y<=y2)return true;
return false;
}
函数原理这里就不多解释了,相关内容可以参考:
C++ 获取鼠标点击位置 https://blog.csdn.net/wangxun20081008/article/details/113915805
C++ 移动光标 https://blog.csdn.net/wangxun20081008/article/details/115560811
完成了这些,我们来编写主函数。
先初始化控制台窗口,用system函数设置窗口的大小、字体颜色,详细内容可以参考:
C++ 设置字体颜色 https://blog.csdn.net/wangxun20081008/article/details/115046817
接下来移除我们的快速编辑模式,在win10环境下将会被默认开启,开启快速编辑模式会使我们无法点击超链接,而是选择。所以我们先将它移除。
int main() {
//----------初始化窗口----------
system("mode 80,40");
system("color f0");
//----------移除快速编辑模式(对于win10用户)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
}
现在我们开始着手编写超链接了。
先指定一下超链接的名称,emmm…,就选4399好了
在顶上加一些变量:
string str="4399小游戏"; //超链接名称
const int len=str.size()-1; //超链接的长度
bool b=false; //是否访问过该超链接
接下来就来打印我们的超链接了:
//----------打印超链接字幕----------
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
gotoxy(0,0);
printf(str.c_str());
在这里,我们用SetConsoleTextAttribute
函数混合了颜色,
FOREGROUND_BLUE
表示前景是蓝色的
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
表示混合红、蓝、绿这三原色,但是混合结果实际是灰色,所以我们用BACKGROUND_INTENSITY
进行高亮,形成白色。所以背景就是白色。
COMMON_LVB_UNDERSCORE
表示的是下划线,它的颜色跟随前景色
然后,我们用gotoxy函数指定光标到(0,0)除位置,打印超链接。
整合1
我们的超链接打印就完成了,整合一下代码。
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/stdc++.h>
using namespace std;
#define key_down(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)//检测按键按下
HWND hwnd=GetForegroundWindow();
string str="4399小游戏";
const int len=str.size()-1;
bool b=false;
void gotoxy(int x, int y) { //设置光标位置(行,列)
COORD pos = {y,x};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
POINT mouse_pos() { //鼠标位置(行,列)
CONSOLE_FONT_INFO consoleCurrentFont;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
POINT p;
GetCursorPos(&p);
ScreenToClient(hwnd,&p); //获取鼠标在窗口上的位置
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
int x=p.x/=consoleCurrentFont.dwFontSize.X;
int y=p.y/=consoleCurrentFont.dwFontSize.Y;
p={y,x};
return p;
}
bool press(int x1,int y1,int x2,int y2) { //鼠标是否在矩形区域内
POINT p;
p=mouse_pos();
if(p.x>=x1&&p.x<=x2&&p.y>=y1&&p.y<=y2)return true;
return false;
}
int main() {
//----------初始化窗口----------
system("mode 80,40");
system("color f0");
//----------移除快速编辑模式(对于win10用户)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------打印超链接字幕----------
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
gotoxy(0,0);
printf(str.c_str());
return 0;
}
运行效果良好,然后我们要开始检测鼠标点击事件。
回到我们刚开始写道的三个函数:
#define key_down(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)//检测按键按下
POINT mouse_pos() { //鼠标位置(行,列)
CONSOLE_FONT_INFO consoleCurrentFont;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
POINT p;
GetCursorPos(&p);
ScreenToClient(hwnd,&p); //获取鼠标在窗口上的位置
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
int x=p.x/=consoleCurrentFont.dwFontSize.X;
int y=p.y/=consoleCurrentFont.dwFontSize.Y;
p={y,x};
return p;
}
bool press(int x1,int y1,int x2,int y2) { //鼠标是否在矩形区域内
POINT p;
p=mouse_pos();
if(p.x>=x1&&p.x<=x2&&p.y>=y1&&p.y<=y2)return true;
return false;
}
我们用key_down函数来检测是否有鼠标点击事件;用press函数来检测鼠标是否在超链接上。
将两个函数结合起来,来检测鼠标是否点击超链接。
//----------检测是否有点击事件----------
while(1) {
if((hwnd == ::GetForegroundWindow())) {
if(key_down(VK_LBUTTON)) {
while(key_down(VK_LBUTTON))Sleep(50);
if(press(0,0,0,len)) {
balabala
}
}
}
Sleep(50);
}
在这里,我们用(hwnd == ::GetForegroundWindow())
来判断窗口是否在顶层(不在顶层怎么点?隔着窗口点??),(key_down(VK_LBUTTON))
用来检测是否有鼠标左键的点击事件
while(key_down(VK_LBUTTON))Sleep(50);
这一行则是为了等鼠标左键抬起,再执行下面的语句。
if(press(0,0,0,len))
再看这一行,当鼠标位置在【(第0行,第0列)到(第0行,第len列)】时(超链接的位置),那么再访问4399的网站。
那么点击了超链接会发生什么呢,添加下面的代码:
system("start www.4399.com");
b=true;
用system函数打开www.4399.com,然后将b(是否访问过该超链接)的值设为true。
整合2
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/stdc++.h>
using namespace std;
#define key_down(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)//检测按键按下
HWND hwnd=GetForegroundWindow();
string str="4399小游戏";
const int len=str.size()-1;
bool b=false;
void gotoxy(int x, int y) { //设置光标位置(行,列)
COORD pos = {y,x};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
POINT mouse_pos() { //鼠标位置(行,列)
CONSOLE_FONT_INFO consoleCurrentFont;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
POINT p;
GetCursorPos(&p);
ScreenToClient(hwnd,&p); //获取鼠标在窗口上的位置
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
int x=p.x/=consoleCurrentFont.dwFontSize.X;
int y=p.y/=consoleCurrentFont.dwFontSize.Y;
p={y,x};
return p;
}
bool press(int x1,int y1,int x2,int y2) { //鼠标是否在矩形区域内
POINT p;
p=mouse_pos();
if(p.x>=x1&&p.x<=x2&&p.y>=y1&&p.y<=y2)return true;
return false;
}
int main() {
//----------初始化窗口----------
system("mode 80,40");
system("color f0");
//----------移除快速编辑模式(对于win10用户)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------打印超链接字幕----------
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
gotoxy(0,0);
printf(str.c_str());
//----------检测是否有点击事件----------
while(1) {
if((hwnd == ::GetForegroundWindow())) {
if(key_down(VK_LBUTTON)) {
while(key_down(VK_LBUTTON))Sleep(50);
if(press(0,0,0,len)) {
system("start www.4399.com");
b=true;
}
}
}
Sleep(50);
}
return 0;
}
链接成功!
之前我们说过访问过超链接后链接的颜色将变为紫色,那么我们开始吧:
if(b==false) {
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
} else {
SetConsoleTextAttribute(hOut,
37|
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
}
gotoxy(0,0);
printf(str.c_str());
如果b是true,那么颜色应该变为紫色,也就是37(这里就简写好了),如果b是false,就照原来那些打印就行了。
整合3
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/stdc++.h>
using namespace std;
#define key_down(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)//检测按键按下
HWND hwnd=GetForegroundWindow();
string str="4399小游戏";
const int len=str.size()-1;
bool b=false;
void gotoxy(int x, int y) { //设置光标位置(行,列)
COORD pos = {y,x};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
POINT mouse_pos() { //鼠标位置(行,列)
CONSOLE_FONT_INFO consoleCurrentFont;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
POINT p;
GetCursorPos(&p);
ScreenToClient(hwnd,&p); //获取鼠标在窗口上的位置
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
int x=p.x/=consoleCurrentFont.dwFontSize.X;
int y=p.y/=consoleCurrentFont.dwFontSize.Y;
p= {y,x};
return p;
}
bool press(int x1,int y1,int x2,int y2) { //鼠标是否在矩形区域内
POINT p;
p=mouse_pos();
if(p.x>=x1&&p.x<=x2&&p.y>=y1&&p.y<=y2)return true;
return false;
}
int main() {
//----------初始化窗口----------
system("mode 80,40");
system("color f0");
//----------移除快速编辑模式(对于win10用户)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------打印超链接字幕----------
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
gotoxy(0,0);
printf(str.c_str());
//----------检测是否有点击事件----------
while(1) {
if((hwnd == ::GetForegroundWindow())) {
if(b==false) {
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
} else {
SetConsoleTextAttribute(hOut,
37|
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
}
gotoxy(0,0);
printf(str.c_str());
if(key_down(VK_LBUTTON)) {
while(key_down(VK_LBUTTON))Sleep(50);
if(press(0,0,0,len)) {
system("start www.4399.com");
b=true;
}
}
}
Sleep(50);
}
return 0;
}
好了,现在超链接是紫色的了,表示我们已经访问了这个网站,完成!
3.完善超链接
什么,你以为这就结束了?
OH!NO!no!no!no!
我们的超链接完成了,但是还有一个缺陷,当将鼠标放在超链接上时,我们应该让用户知道他的鼠标移到了这个超链接上。
所以,我们应该让字体出现阴影,我们只需要将——不知道你还记不记得,字体的背景色有个高亮值——高亮取消。
if(press(0,0,0,len)) {
if(b==false) {
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN |
COMMON_LVB_UNDERSCORE);
} else {
SetConsoleTextAttribute(hOut,
37|
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN |
COMMON_LVB_UNDERSCORE);
}
gotoxy(0,0);
printf(str.c_str());
} else {
if(b==false) {
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
} else {
SetConsoleTextAttribute(hOut,
37|
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
}
gotoxy(0,0);
printf(str.c_str());
}
整合4 - 大功告成
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/stdc++.h>
using namespace std;
#define key_down(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)//检测按键按下
HWND hwnd=GetForegroundWindow();
string str="4399小游戏";
const int len=str.size()-1;
bool b=false;
void gotoxy(int x, int y) { //设置光标位置(行,列)
COORD pos = {y,x};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
POINT mouse_pos() { //鼠标位置(行,列)
CONSOLE_FONT_INFO consoleCurrentFont;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
POINT p;
GetCursorPos(&p);
ScreenToClient(hwnd,&p); //获取鼠标在窗口上的位置
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
int x=p.x/=consoleCurrentFont.dwFontSize.X;
int y=p.y/=consoleCurrentFont.dwFontSize.Y;
p={y,x};
return p;
}
bool press(int x1,int y1,int x2,int y2) { //鼠标是否在矩形区域内
POINT p;
p=mouse_pos();
if(p.x>=x1&&p.x<=x2&&p.y>=y1&&p.y<=y2)return true;
return false;
}
int main() {
//----------初始化窗口----------
system("mode 80,40");
system("color f0");
//----------移除快速编辑模式(对于win10用户)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------打印超链接字幕----------
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
gotoxy(0,0);
printf(str.c_str());
//----------检测是否有点击事件----------
while(1) {
if((hwnd == ::GetForegroundWindow())) {
if(press(0,0,0,len)) {
if(b==false) {
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN |
COMMON_LVB_UNDERSCORE);
} else {
SetConsoleTextAttribute(hOut,
37|
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN |
COMMON_LVB_UNDERSCORE);
}
gotoxy(0,0);
printf(str.c_str());
} else {
if(b==false) {
SetConsoleTextAttribute(hOut,
FOREGROUND_BLUE |
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
} else {
SetConsoleTextAttribute(hOut,
37|
BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_INTENSITY |
COMMON_LVB_UNDERSCORE);
}
gotoxy(0,0);
printf(str.c_str());
}
if(key_down(VK_LBUTTON)) {
while(key_down(VK_LBUTTON))Sleep(50);
if(press(0,0,0,len)) {
system("start www.4399.com");
b=true;
}
}
}
Sleep(50);
}
return 0;
}
完美!
4.小结
现在我们的超链接完成了,这次我们运用了很多C++控制台游戏编程的基本函数,想了解更多就关注我吧。本章到此就告一段落了,再见!