中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » [分享]一个弹出式窗口类(C++源码)
作者:
标题: [分享]一个弹出式窗口类(C++源码) 上一主题 | 下一主题
awangwjf
新手上路





积分 7
发帖 3
注册 2010-2-26
状态 离线
『楼 主』:  [分享]一个弹出式窗口类(C++源码) 使用 LLM 解释/回答一下

这是《C++大全》上的一个DOS下弹出式窗口类C++示例,使用直接写视频VRAM方法实现窗口的显示,在DOS后期是一种成熟、使用率较高的方法。


窗口类的I/O层用纯C++代码+BIOS中断实现,没用一个标准库函数。(除了速度快以外,这种代码比较易移植)


下面是该类完整的C++源码,包含用于演示的一个简单的main,该示例思路清晰,代码实现简洁易理解,是学习C++用于面向对象设计的较好的入门级示例。


代码在BC++3.1上编译通过。


/////////////////////////////////////////////////////////////////////////////
//
// A window class
// PASS BC++ 3.1
// From CPP P633
// Type by AW@ng
//
// Form http://www.cn-dos.net/forum/
//
/////////////////////////////////////////////////////////////////////////////


#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <bios.h>
#include <stdio.h>

/////////////////////////////////////////////////////////////////////////////
//
// Globe functions and data declare
//
/////////////////////////////////////////////////////////////////////////////



/* Text colors, first 7 can also be used to specify
background color.
*/
const enum clr {black, blue, green, cyan, red, magenta,
brown, lightgray, darkgray, lightblue,
lightgreen, lightcyan, lightred,
lightmagenta, yellow, white, blink=128};


char far *vid_mem; //pointer to screen memory when in text mode


int video_mode();
void goto_xy(int x, int y);
void set_v_ptr();
void write_char(int x, int y, char ch, int attrib);
void write_string(int x, int y, char *p, int attrib);


/////////////////////////////////////////////////////////////////////////////
//
// End Globe declare
//
/////////////////////////////////////////////////////////////////////////////
//
// Start globe function define
//
/////////////////////////////////////////////////////////////////////////////


//Return the current video mode
video_mode(void)
{
union REGS r;

r.h.ah = 15;

return int86(0x10, &r, &r) & 255;
}


//Set video mode video_address
void set_v_ptr()
{
int vmode;

vmode = video_mode();
if((vmode != 2) && (vmode != 3) && (vmode != 7))
{
cout << endl
<< "Video must be in 80 column text mode"
<< endl;

exit( 1 );
}

//set proper address of video RAM
if(vmode == 7)
{
vid_mem = (char *)0xB0000000;
}
else
{
vid_mem = (char *)0xB8000000;
}
}



//Write character with specified attribute
void write_char(int x, int y, char ch, int attrib)
{
char far *v;

v = vid_mem;
v += (y *160) + (x * 2);
*v++ = ch;
*v = attrib;
}


//Display string with specified attrib
void write_string(int x, int y, char *p, int attrib)
{
register int i;
char far *v;

v = vid_mem;
v += (y * 160) + (x * 2);

for(i = y; *p ; i++)
{
*v++ = *p++;
*v++ = attrib;
}
}



//Send the cursor to the specified X, Y position
void goto_xy(int x, int y)
{
union REGS r;

r.h.ah = 2;
r.h.dl = x;
r.h.dh = y;
r.h.bh = 0;

int86(0x10, &r, &r);
}





/////////////////////////////////////////////////////////////////////////////
//
// Start class declare
//
/////////////////////////////////////////////////////////////////////////////

class wintype
{
int leftx; //define where window goes on the screen
int upy; //upper left coordinate
int rightx;
int downy; //lower right coordinate

int border; //if non-zero,border displayed
int active; //non-zero if window is currently on screen
char *title; //window title

int curx, cury; //current cursor location in window

char *buf; //points to window's buffer

char color; //window text color


//private functions
void save_screen(); //save screen so it can be restored
void restore_screen(); //restore the original screen
void draw_border(); //draw a window's border
void display_title(); //display window title

public:
wintype(int lx, int uy, //upper left
int re, int ly, //lower right
int b = 1, //non-zero for border
char *mess = ""); //title message

~wintype()
{
winremove();
delete buf;
}


void winput(); //display a window
void winremove(); //remove a window
int winputs(char *s); //write a string to the window
int winxy(int x, int y); //go to X, Y relative to window
void wingets(char *s); //input a string from a window
int wingetche(); //input a character from a window
void wincls(); //clears the window
void wincleol(); //clears to end-of-line

void setcolor(char c) {color = c; }
char getcolor() {return color; }
void setbkcolor(char c) {color = (color | (c << 4)); }
char getbkcolor() {return (color >> 4) & 127; }


friend wintype &operator << (wintype &o, char *s);
friend wintype &operator >> (wintype &o, char *s);
};

/////////////////////////////////////////////////////////////////////////////
//
// End class declare
//
/////////////////////////////////////////////////////////////////////////////



//Construct a window.
wintype::wintype(int lx, int uy,
int rx, int ly,
int b,
char *mess )
{
if(lx < 0 ) lx = 0 ;
if(rx > 79) rx = 79;
if(uy < 0 ) uy = 0 ;
if(ly > 24) ly = 24;

leftx = lx ;
upy = uy ;
rightx = rx ;
downy = ly ;
border = b ;
title = mess ;
active = 0 ;
curx = cury = 0;

buf = new char;
if( !buf )
{
cout << "\nAllocation window buffer error\n";
exit( 1 );
}

color = white;
}


//Display a window
void wintype::winput()
{
//get active window
if( !active ) //not currently in use
{
save_screen(); //save the current screen
active = 1; //set active flag
}
else
{
return; //already on screen
}

if( border )
{
draw_border();
}
display_title();

//position cursor in apper left corner
goto_xy(leftx + curx + 1, upy + cury +1);
}


//Remove the window and restore prior screen contents.
void wintype::winremove()
{
if(!active) //con't remove a non-active window
{
return;
}

restore_screen(); //restore the original screen
active = 0; //restore_video
}


//Draw a border around the window
void wintype::draw_border()
{
register int i;
char far *v;
char far *t;

v = vid_mem;
t = v;

for(i = leftx + 1; i < rightx; i++)
{
v += (upy * 160) + (i * 2);
*v ++ = 196;
*v = color;
v = t;
v += (downy * 160) + (i * 2);
*v ++ = 196;
*v = color;
v = t;
}

for(i = upy + 1; i < downy; i++)
{
v += (i * 160) + (leftx * 2);
*v ++ = 179;
*v = color;
v = t;
v += (i * 160) + (rightx * 2);
*v ++ = 179;
*v = color;
v = t;
}

//draw the corners
write_char(leftx, upy, 218, color);
write_char(leftx, downy, 192, color);
write_char(rightx, upy, 191, color);
write_char(rightx, downy, 217, color);
}


//Display the window's title
void wintype::display_title()
{
register int x, len;

x = leftx;
len = strlen(title);
len = (rightx - x- len)/2;
if( len < 0 ) return;

x = x + len +1;

write_string(x, upy, title, color);
}


//Save screen so ti can be restored after window is removed
void wintype::save_screen()
{
register int i, j ;
char far *v ;
char far *t ;
char *buf_ptr ;


buf_ptr = buf;
v = vid_mem;
for(i = upy; i < downy+1; i++)
{
for(j = leftx; j < rightx+1; j++)
{
t = (v + (i*160) + (j*2));
*buf_ptr++ = *t++;
*buf_ptr++ = *t;
*(t - 1) = ' '; //clear the window
}
}
}


//Restore a portion of the screen
void wintype::restore_screen()
{
register int i, j ;
char far *v ;
char far *t ;
char *buf_ptr ;


buf_ptr = buf; //computer pointer to video RAM
v = vid_mem;
t = v;

for(i = upy; i < downy+1; i++)
{
for(j = leftx; j < rightx+1; j++)
{
v = t;
v += (i*160) + j*2;
*v++ = *buf_ptr++; //write the character
*v = *buf_ptr++; //write the attrib
}
}
}


//Write a string at the current cursor position win the specified window
int wintype::winputs(char *s)
{

register int x, y;
char far *v;


//make sure window is active
if ( !active ) return 0;


x = curx + leftx + 1;
y = cury + upy + 1;

v = vid_mem;
v += (y * 160) + (x * 2);

for( ; *s; s++ )
{
if(y >= downy)
{
return 1;
}
if(x >= rightx)
{
return 1;
}

if(*s == '\n')
{
y++;
x = leftx + 1;
v = vid_mem;
v += (y * 160) + (x * 2);;
cury++;
curx = 0;
}
else
{
curx++;
x++;
*v++ = *s;
*v++ = color;
}

winxy(curx,cury);
}

return 1;
}


/* Postion cursor in a window at specified location
Return 0 if out of range; non-zero otherwise.
*/
int wintype::winxy(int x, int y)
{
if(x < 0 || x+leftx >= rightx-1)
{
return 0;
}
if(y < 0 || y+upy >= downy-1)
{
return 0;
}

curx = x;
cury = y;
goto_xy(leftx + x + 1, upy + y + 1);

return 1;
}


//read a string from a window
void wintype::wingets(char *s)
{
char ch, *temp;

temp = s;

for(;;)
{
ch = wingetche();

switch(ch)
{
case '\r' :
{
*s = '\0';
return ;
}

case '\b' :
if(s > temp)
{
s--;
curx--;

if(curx < 0)
{
curx = 0;
}

winxy(curx, cury);
write_char(leftx + curx + 1, upy + cury +1, ' ', color);
}
break;

default :
{
*s = ch;
s++;
}
}
}
}



/* Input a keystroke inside a window
Returns full 16 bit keyboard code.
*/
wintype::wingetche()
{
union inkey
{
char ch;
int i;
} c;
union REGS r;


if( !active ) return 0;


winxy(curx, cury);

r.h.ah = 0;
c.i = int86(0x16, &r, &r);

if( c.ch )
{
switch( c.ch )
{
case '\r' :
{
break;
}

case '\b' :
{
break;
}

default:
{
if( curx + leftx < rightx -1 )
{
write_char(leftx + curx +1,
upy + cury +1,
c.ch,
color );
curx++;
}
}
}
}

if(cury < 0) cury = 0;
if(cury + upy > downy -2)
{
cury--;
winxy(curx, cury);
}

return c.i;
}


//Clear a window
void wintype::wincls()
{
register int i, j;
char far *v, far *t;

v = vid_mem;
t = v;

for(i = upy +1; i < downy; i++)
for(j = leftx + 1; j < rightx; j++)
{
v = t;
v += (i * 160) + (j * 2);
*v++ = ' ';
*v = color;
}

curx = 0;
cury = 0;
}


//Clear to end of line
void wintype::wincleol()
{
register int i, x, y;


x = curx;
y = cury;
winxy(curx, cury);

for(i = curx; i < rightx; i++)
{
winputs(" ");
}

winxy(x, y);
}


//Output to a window
wintype &operator << (wintype &o, char *s)
{
o.winputs(s);
return o;
}


//Input from a window
wintype &operator >> (wintype &o, char *s)
{
o.wingets(s);
return o;
}



/////////////////////////////////////////////////////////////////////////////
//
// Main program here
//
/////////////////////////////////////////////////////////////////////////////
main()
{
char s;



set_v_ptr(); //set the video memory pointer


wintype w1(1, 10, 20, 20, 1, "My window #1");
wintype w2(40, 1, 60, 20, 1, "My window #2");
wintype w3(40, 5, 60, 20, 2, "My window #3");


w1.winput();
w2.winput();

w1.setcolor(blue);
w2.setcolor(green);
w3.setcolor(red);
getch();

w1.winremove();
w2.winremove();
getch();

w1.winput();
w2.winput();
w3.winput();
getch();


w1.winremove();
getch();

w3.winremove();
getch();

w2.winremove();
getch();



w1.winput();
w2.winput();
getch();

w1 >> s;
w1.winxy( 0, 0 );
getch();

w1.winputs("Hi there\n");
w1.winputs("Windows is fan");
w1 << "\n";
w1 >> s;
w1 << "This \nis " << "a test" << "\n";
w2 << "this is a test";
w2.winxy(3, 4);
w2 << "at location 3,4";
w1 << "This is anther test for you to see\n";
w1 >> s;

w3.winput();
w3 >> s;
w3.winremove();
getch();


w1.winxy(0, 0);
w1.setcolor(red);
w1.setbkcolor(cyan);
w1.winputs("PROMPT:");
w1.setcolor(white);
w1.setbkcolor(black);
w1 >> s;

w2.winxy(0, 4);
w2.setcolor(yellow);
w2.setbkcolor(green);
w2.winputs(s);
w2 >> s;

w2.wincls();
w1.winxy(5, 0);
w1.wincleol();
w2 >> s;

w1.winremove();
w2.winremove();
w1.winput();


w1 >> s;


return 0;
}





BC++下的代码copy到Win下有个别地方显示板式不同,没太大影响,没做调整。


这个示例是我学习C++的时候完成的,代码中的字符都是本人一个个敲进电脑的,一是为了学习BC++3.1的IDE,另外也能加深对代码的理解,书中个别印错的地方已经修正。现发上来和初学C++的朋友和爱好者共享。


那时的C++实现标准是1989年的2.1版,没现在这么复杂,模板和异常还是发展方向,名字空间,泛型听都没听说过,正因为这样,更能有助于学习C++面向对象的思维方法,而不是专注于代码的实现,这才是C++和C的本质区别。


2.1版的C++个人认为是比较纯淬的C++,能很好的用OO实现C++的初衷“使程序结构清晰、易于扩展、易于维护而不失其效率”,没有多余的东西,“增一分太肥,减一分太瘦”。


现在C++加入了各种“先进”的特性后,发展到目前的C++0X,连C++的发明人也不得不承认有些“四不象”了,真可惜了这一优美的程序设计语言。


题外:
关于BC++3的经典有了最新证据,Win7下的BC++3.1比在Windows3.1时代好用,把“环境”项里的25行显示改为50行,再得宜于Win7完善高效的内存管理,用起来真是舒服,再看看Win7的自家人VC6,“该程序有兼容性问题,请......”,我真的哭笑不得。

以前的ID不知为什么不能登录了,重注册了一个。


2010-2-27 12:50
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
stockghost
中级用户





积分 215
发帖 105
注册 2007-6-2
状态 离线
『第 2 楼』:   使用 LLM 解释/回答一下

都是DOS老人,同好!
Win9x/2k/xp都支持DOS程序,而且也支持dos32(不管是watcom还是djgpp编译出来的),但在vista测试,上述两种程序都不支持.
Win7没用过,支持DOS?
如果支持,估计也支持dos32.


2010-2-27 17:30
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复
BA_WANG_MAO
初级用户




积分 147
发帖 13
注册 2005-3-25
状态 离线
『第 3 楼』:   使用 LLM 解释/回答一下

dos时刻最经典的"直接写屏"模式,绕开DOS的API和BIOS,直接对显存编程,提高显示速度.


2010-3-3 10:23
查看资料  发送邮件  发短消息  网志   编辑帖子  回复  引用回复

请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: