QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2980|回复: 8

几个常见控件的有趣的画法

[复制链接]
发表于 2006-4-12 17:18:17 | 显示全部楼层 |阅读模式
图中所示的效果有2个关键技术。当然这个技术不难。看GTK的代码很容易看到,这里我既然做EGui的时候学习。我就想告诉大家。或许我们日常我们也看了但是没有仔细想而已。那么到底他们是怎么做出来的呢?

1. button
   大家都知道一般按钮在显示的时候有一种凸出效果。
   
2. edit
   一般的都是凹陷进去的。

那么他们是怎么实现的呢?实际上gtk里有个shadow.函数实现了他。以上2个控件是一种技术。正反2种用法而已。

看代码。
[code:1]
int
Egui_shadow_out (int x,int y, int w,int h,EGui_Window * window)
{
      int i = 0;
      Ecolor color;

      new_color( window,&color,0xA0A0A0);
      Egui_rect (x+i,y+i,w-i-2,h-i-2, &color, window);
      
      i++;
      new_color( window,&color,0xF0F0F0);
      /* left vertical */
      Egui_line (x+i,y+i,x+i,h-i-2, &color, window);
      /* up horizontal */
      Egui_line (x+i,y+i,w-i-2,y+i, &color, window);
      
      new_color( window,&color,0x808080);
      /* right vertical */
      Egui_line (w-i,y+i-1,w-i,h-i, &color, window);
      /* bottom horizontal */
      Egui_line (x+i-1,h-i,w-i,h-i, &color, window);     

}


int
Egui_shadow_in (int x,int y,int w,int h,EGui_Window * window)
{
      int i = 0;
      Ecolor color;

      new_color( window,&color,0xA0A0A0);
      Egui_rect (x+i,y+i,w-i-2,h-i-2, &color, window);
      
      i++;
      new_color( window,&color,0x808080);   
      /* left vertical */
      Egui_line (x+i,y+i,x+i,h-i-2, &color, window);
      /* up horizontal */
      Egui_line (x+i,y+i,w-i-2,y+i, &color, window);
      
      new_color( window,&color,0xF0F0F0);
      /* right vertical */
      Egui_line (w-i,y+i-1,w-i,h-i, &color, window);
      /* bottom horizontal */
      Egui_line (x+i-1,h-i,w-i,h-i, &color, window);     

      i++;
      new_color(window,&color,0xEDEDED);
      Egui_fill (x+i,y+i,w-i-1,h-i-1, &color, window);
}[/code:1]
代码都差不多,就是颜色换一种玩法而已。

首先画个矩形。在矩形的左上角的内侧画2条相对的白线,右下角化2条相对的黑线。这就是凸出效果。
反之就是凹陷效果。

怎么样?你也可你试一下。


3. disable click
  这是第2种关键技术。大家都知道,为了告诉用户这个按钮不能单击,系统用了灰色效果。
  字有些凹陷的样子。这是怎么做出来的呢?

  看看代码:
    [code:1]  new_color(window,&color,0xFFFFFF);
      Egui_drawstring(x + 6,y + 3,widget->name,font,&color,window);

      new_color(window,&color,0x747474);
      Egui_drawstring(x + 5,y + 2,widget->name,font,&color,window);[/code:1]   先用白色将字画一遍。再用常用的暗灰色画一遍。
   注意:白色的字的位置是暗灰色的字右下的row,col都移一个像素。
         先画白色的字体。

欢迎沟通图形问题。
asmcos 2006-04-12 www.egui.org[code:1][/code:1]

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| 发表于 2006-4-14 08:44:08 | 显示全部楼层
edit控件正在更新.过一段时间就可以交互了.
回复

使用道具 举报

 楼主| 发表于 2006-4-14 12:34:31 | 显示全部楼层
edit 基本可以用了.
回复

使用道具 举报

发表于 2006-5-21 19:17:53 | 显示全部楼层
想请教一下vscrollbar(垂直滚动条)设计的原理,我看现在有些控件是按象素的,又有按行的
回复

使用道具 举报

发表于 2006-5-21 19:45:03 | 显示全部楼层
我选择的作法是:
Scrollbar向相应视图(View)调用ScrollTo成员,
至于如何操作由View自身决定,它可以依赖像素,
也可以按特定方式(如:行、列等)进行变换。
回复

使用道具 举报

发表于 2006-5-21 20:27:52 | 显示全部楼层
[quote:da492bb546="AnthonyLee"]我选择的作法是:
Scrollbar向相应视图(View)调用ScrollTo成员,
至于如何操作由View自身决定,它可以依赖像素,
也可以按特定方式(如:行、列等)进行变换。[/quote]

不是很明白,View怎么自己决定,比如list View的Doc超过View,而且View不能被Doc的每一行高整除时候,这种情况,如何确定scrollbar中间的滑动条的高度
回复

使用道具 举报

发表于 2006-5-22 00:55:26 | 显示全部楼层
[quote:e755bfd989="fhml"]
不是很明白,View怎么自己决定,比如list View的Doc超过View,而且View不能被Doc的每一行高整除时候,这种情况,如何确定scrollbar中间的滑动条的高度[/quote]

也不大明白您的意思,不知以下这样说行不行。

假如有一个Doc,它的实际占用范围高度(Hr)超过可视范围高度(Hv)
而垂直ScrollBar的滑动条最大可用高度假如为Hs,
则按以下原则确定滑动条的区域Y坐标(按pixel方式,Y值由上至下递增):
[code:1]
第一种情况: 如果Hs > (Hr - Hv)
        Ytop = Yorigin(滑动条可绘区域的最小Y值) + Doc已偏移的Y向相对坐标量
        Ybottom = Ytop + (Hs - (Hr - Hv))

第二种情况: 如果Hs <= (Hr - Hv)
        Ycenter = Yorigin + Doc已偏移的Y向相对坐标量 * Hs / (Hr - Hv)
        再按规定的最小滑块高度确定相应的Ytop和Ybottom
[/code:1]
按行的时候可以把上述相应改一改,也可以根据每一行的像素高度变换成相应的值。

至于如何由View决定,这个视乎您所指的是哪个Toolkit了。
以下可能讲的还是不清楚,只是一些大体的方法,具体实现视乎您自己。
比如(C++,C的widget其实也差不多):

View有以下成员:
[code:1]
virtual void ScrollTo(int x, int y);
[/code:1]

再而View派生出一个类Doc,它override掉ScrollTo成员函数,
[code:1]
virtual void Doc::ScrollTo(int x, int y)
{
        if(按像素方式)
        {
                if(x 和 y 值允许的话)
                {
                        设置偏移量;
                        重画本身可视范围内的内容;
                }
        }
        else if(按行方式)
        {
                int nx = 按x,y,每行高度计算;
                int ny = 按x,y,每行高度计算;
                按nx,ny设置偏移量;
                按nx,ny重画本身可视范围内的内容;
                按nx,ny设置ScrollBar的偏移量或做其它的;
        }
}
[/code:1]

每一次ScrollBar有所动作时根据相应规则调用(View*)Doc->ScrollTo()就可以了。
回复

使用道具 举报

 楼主| 发表于 2006-5-22 08:43:03 | 显示全部楼层
应该按照要滚动的内容定,如果字符可以按照行,如果是图片,应该按照像素.
回复

使用道具 举报

发表于 2006-5-27 00:11:08 | 显示全部楼层
实际上我想说的是scrollbar的高度是可变的,即随doc和view的高度(以垂直滚动条为例)

下面是我的的一点不成熟的按行的想法,还请大家指点,无实践 f(x)表示 "x的f"

1.
如果h(doc) <= h(view)
h(scrollbar) =maxheight(scrollbar);//最大可用高度
否则
h(scrollbar) =maxheight(scrollbar) - dv(scrollbar) * (line(doc) - line(view));
2.
垂直步长dv (为scrollbar按一下上下移动的垂直高度)
dv(scrollbar) = maxheight(scrollbar)/ line(doc);

只是有个问题就是h(view) % linehight(doc) !=0时候比较难处理

而且每一种控件都要即时计算line(doc)和line(view),不知道有没有更好的办法
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-2 14:18 , Processed in 0.044382 second(s), 17 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表