DevGUI 使用方法
DevGUI 使用方法
一、最简单的 DevGUI 程序
安装完 DevGUI 后,打开 Dev-C++,新建源代码,输入以下程序:
#include <dgui.h>
int main(){
setup();
keepwindow();
return 0;
}
运行效果:
那个白色的窗口就是著名的 GUI 界面。
这里面的 setup 是创建窗口,keepwindow 是等待窗口关闭后才返回。
就这么简单。
二、DevGUI 基本结构
DevGUI 图形库主要由几个头文件构成,所有内容都在一个名字空间 dgui_ns 中(v2.1 及之前为 dgui,旧版程序可以使用此方法)。
dgui.h 里有 using namespace dgui_ns;,所以程序中不需要写。如果不想自动包含,可以 在 #include <dgui.h> 之前 写上以下代码:
#define _DGUI_NOUSINGNAMESPACE_
DevGUI 图形库自动包含以下标准库头文件:
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdarg>
#include <cmath>
#include <vector>
#include <string>
#include <queue>
#include <map>
自动包含以下 Windows 头文件:
#include <process.h>
#include <windows.h>
#include <mmsystem.h>
自动 using 以下内容:
using std::vector;
using std::string;
using std::queue;
using std::map;
(不包含 using namespace std;)
DevGUI 有两种模式:源代码和项目,Dev-C++ 直接新建出来的代码就是源代码,Dev-C++ 的 “文件 -> 新建” 里还可以新建项目。
源代码比较常用,因此大部分内容在源代码中测试。如果要在项目中使用,用法基本相同,但是需要 在 #include <dgui.h> 之前 加上以下代码:
#define PROJECT
注意:这个只能在项目中使用,在源代码中使用会导致大量编译错误。
三、DevGUI 中的函数等
注意:只列出常用的,不是 DevGUI 的所有内容。
1.窗口基本操作
setup 函数——创建窗口
setup 函数有多种重载的形式:
void setup(int x,int y,int w,int h,string title);
指定窗口横纵坐标、宽度、高度、标题。
void setup(int x,int y,int w,int h);
指定窗口横纵坐标、宽度、高度,标题为 无标题。
void setup(int w,int h,string title);
指定窗口宽度、高度、标题,使用默认横纵坐标。
void setup(int w,int h);
指定窗口宽度、高度,使用默认横纵坐标,标题为 无标题。
void setup(string title);
指定窗口标题,使用默认横纵坐标、宽度、高度。
void setup();
不指定窗口的任何信息,使用默认横纵坐标、宽度、高度,标题为 无标题。
修改窗口属性的函数
void settitle(string wndtitle);
修改窗口标题。
void showwindow(int stype);
显示或隐藏窗口。
其中的 stype 有如下取值(定义在系统 winuser.h 的
#define SW_HIDE 0
#define SW_SHOWNORMAL 1
#define SW_NORMAL 1
#define SW_SHOWMINIMIZED 2
#define SW_SHOWMAXIMIZED 3
#define SW_MAXIMIZE 3
#define SW_SHOWNOACTIVATE 4
#define SW_SHOW 5
#define SW_MINIMIZE 6
#define SW_SHOWMINNOACTIVE 7
#define SW_SHOWNA 8
#define SW_RESTORE 9
#define SW_SHOWDEFAULT 10
#define SW_FORCEMINIMIZE 11
#define SW_MAX 11
它们的作用就是字面意思。
void showwindow();
显示窗口。
void movewindow(int x,int y,int w,int h);
移动窗口到指定坐标,并将窗口宽度、高度设置为指定数值。
void poswindow(int x,int y);
移动窗口到指定坐标。
void resizewindow(int w,int h);
设置窗口宽度、高度。
其他
void hideconsole();
隐藏控制台。
旧版 bug:旧版中如果屏幕上有其他控制台窗口,这个函数可能会隐藏其他控制台,最新版无此 bug。
bool windowexist();
判断程序创建的窗口是否存在。存在返回
void keepwindow();
一直等待,直到窗口被关闭。
long long winfo(string key);
获取窗口的某一项信息。
有效的调用方式有:
winfo("x");//窗口横坐标
winfo("x");//窗口纵坐标
winfo("window-x");//窗口横坐标 同 "x"
winfo("window-x");//窗口纵坐标 同 "y"
winfo("client-x");//窗口客户区横坐标
winfo("client-y");//窗口客户区纵坐标
winfo("width");//窗口客户区宽度
winfo("height");//窗口客户区高度
如果 key 无效,会返回
void closewindow();
关闭窗口。
2.画图操作
数据类型
DPOINT 表示一个点
int x横坐标int y纵坐标
DPOINTS 表示一个 DPOINT 类型的数组
DRECT 表示一个矩形
int x1左上角横坐标int y1左上角纵坐标int x2右下角横坐标int y2右下角纵坐标
DCOLOR 或 DCOL 表示一种颜色(相当于 unsinged int)
函数
void ellipse(int x,int y,int r1,int r2);
指定中心坐标、横向半径、纵向半径,画椭圆。
void circle(int x,int y,int r);
指定圆心坐标、半径,画圆。
void rectangle(DPOINT p1,DPOINT p2);
指定左上角、右下角的点,画矩形。
void rectangle(int x,int y,int a,int b);
指定左上角坐标和横向、纵向边长,画矩形。
void square(int x,int y,int a);
指定左上角坐标和边长,画正方形。
void polygon(int len,DPOINTS pnts);
指定点数和各点,画多边形。
void poly(int len,...);
指定点数和各点坐标(两个数字一组),画多边形。
void line(int x1,int y1,int x2,int y2);
指定左上角、右下角坐标,画线段。
void polyl(int len,...);
指定点数和各点坐标(两个数字一组),画折线。
void textout(int x,int y,string txt);
void openconsole(void);
创建控制台。
void consoleout(string str);
在控制台中输出字符串。
void cputs(const char *s);
相当于 puts。
char cputc(char c);
相当于 putchar。
int cprintf(const char *fmt,...);
相当于 printf。
注意:关于速度,这些函数都是用 consoleout 实现的,理论上 consoleout 最快。
10.音乐操作
注意:如果涉及到音乐文件,只支持 .wav 文件,其他格式请转换成 WAV 后使用。
目前我发现比较好用的是 这个网站。
void beep(int freq,int tim);
发出频率为
void playmusic(string path);
异步播放音乐,调用后立即返回,音乐与之后的程序同时运行。
void finishmusic(string path);
同步播放音乐,音乐播完后返回。
void playmusicuntilend(string path);
相当于 finishmusic。
void playmusicloop(string path);
异步循环播放音乐,调用后立即返回,之后音乐循环播放。
void stopallmusic();
停止所有音乐。
11.版本信息
int verval(int idx);
获取版本信息第
string version();
获取简短的版本号字符串。
string longversion();
获取完整的版本号字符串。
dver.h 第一行注释
(v2.1 及以后)表示版本号。
12.杂项
UNUSED(var)
表示变量 var 没有使用。(防止编译器报警告)
(完)
放一个汉诺塔模拟器:
#include <dgui.h>
#include <algorithm>
#define N 67
#define NC 10
#define NCMX 17
#define INF 0x7fffffff
using std::sort;
int n=8;
int twr[5][N],cnt[5];
int sel;
int interv=200;
DCOLOR nodec[NCMX]={
getcolor("red"),
getcolor("orange"),
getcolor("yellow"),
getcolor("lime"),
getcolor("green"),
getcolor("blue"),
getcolor("cyan"),
getcolor("purple"),
getcolor("pink"),
getcolor("grey")
};
DCOLOR framec=getcolor("default");
void tpush(int pos,int id){
twr[pos][++cnt[pos]]=id;
}
int ttop(int pos){
return twr[pos][cnt[pos]];
}
void tpop(int pos){
--cnt[pos];
}
void init(){
cnt[1]=cnt[2]=cnt[3]=0;
for(int i=1;i<=3;++i){
twr[i][0]=INF;
}
for(int i=n;i>=1;--i){
tpush(1,i);
}
}
int getnw(int id){
return 30+(id-1)*10;
}
DCOLOR getnc(int id){
return nodec[(id-1)%NC];
}
void upd(){
setfillcolor(framec);
clear();
rectangle(30,60,100,50);
textout(45,63,"还 原");
rectangle(30,130,100,50);
textout(45,133,"自 动");
rectangle(30,200,100,50);
textout(45,203,"设 置");
/*80 10 160 10 160 10 80*/
rectangle(180,400,510,10);
rectangle(260,100,10,300);
rectangle(430,100,10,300);
rectangle(600,100,10,300);
for(int i=1;i<=3;++i){
for(int j=1;j<=cnt[i];++j){
setfillcolor(getnc(twr[i][j]));
int w=getnw(twr[i][j]);
if(i==sel&&j==cnt[i]){
rectangle(180+85+(i-1)*170-(w>>1),50,w,20);
}
else{
rectangle(180+85+(i-1)*170-(w>>1),400-j*20,w,20);
}
}
}
}
void movenode(int src,int dst){
tpush(dst,ttop(src));
tpop(src);
}
void clickpos(int pos){
if(sel){
if(sel==pos){
sel=0;
}
else{
if(ttop(sel)<ttop(pos)){
movenode(sel,pos);
sel=0;
}
}
}
else{
if(cnt[pos]){
sel=pos;
}
}
upd();
}
void setting(){
string s;
while(1){
s=vbsinput("请输入层数:","汉诺塔");
if(isnumstr(s)){
n=strtoint(s);
break;
}
else{
vbsmsgbox("请输入数字!","汉诺塔",0);
}
}
init();
upd();
}
void cmove(int src,int dst){
clickpos(src);
sleep(interv);
clickpos(dst);
sleep(interv);
}
void solve(int src,int dst,int mcnt){
if(mcnt==0){
return;
}
if(mcnt==1){
cmove(src,dst);
return;
}
int mid=6-src-dst;
solve(src,mid,mcnt-1);
cmove(src,dst);
solve(mid,dst,mcnt-1);
}
void autosolve(){
init();
upd();
sleep(interv);
solve(1,3,n);
}
void onmouse(EPARA p){
UNUSED(p);
static DRECT r1=DRECT(30,60,130,110),
r2=DRECT(30,130,130,180),
r3=DRECT(30,200,130,250);
DPOINT pos=mousepos();
int x=pos.x,y=pos.y;
if(inrect(pos,r1)){
init();
upd();
}
if(inrect(pos,r2)){
autosolve();
}
if(inrect(pos,r3)){
setting();
}
if(x<180||x>690||y>410){
return;
}
if(x==690){
x=689;
}
clickpos((x-180)/170+1);
}
void onkey(EPARA p){
int vk=transepara<int>(p);
switch(vk){
case '1':{
clickpos(1);
break;
}
case '2':{
clickpos(2);
break;
}
case '3':{
clickpos(3);
break;
}
case 'I':{
init();
upd();
break;
}
case 'A':{
autosolve();
break;
}
case 'S':{
setting();
break;
}
}
}
int main(){
hideconsole();
setup(750,550,"汉诺塔");
init();
setting();
upd();
bind("MouseDown-L",onmouse);
bind("KeyDown",onkey);
keepwindow();
return 0;
}