posts - 21,  comments - 60,  trackbacks - 3

学习新的图形库时有个习惯,就是将罗云彬先生的一个闹钟小程序移植到这个图形库下。

原理也很简单,就是通过图片以第一个点的颜色为透明色创建窗体,但Gtk#创建就有些费劲了,主要是因为Gtk#的原生库Gtk+为C写的,有很多指针操作,在C#下有些麻烦,查了好多资料才写了下面几句代码。

然后用Cairo绘制时钟的时间,也是一张图片,然后按时、分、秒截取图形的一部分绘制到不透明窗体上。

在Windows 7、Ubunu 11.04下运行,效果相同。

见代码:

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using Cairo;
  6 using Gdk;
  7 using Gtk;
  8 using Window = Gtk.Window;
  9 using WindowType = Gtk.WindowType;
 10 
 11 namespace GClock
 12 {
 13     public class MainWindow : Window
 14     {
 15         bool timer = true;
 16         readonly Pixbuf _pixbufNumber;      // 时钟时间图片,为0-9十个数字和:以及空白部分组成
 17 
 18         public MainWindow()
 19             : base(WindowType.Toplevel)
 20         {
 21             _pixbufNumber = new Pixbuf(GetType().Assembly, "GClock.Bmp.Number06.bmp");
 22 
 23             // 从嵌入资源中获取Pixbuf
 24             var pixbufO = new Pixbuf(GetType().Assembly, "GClock.Bmp.Clock03.bmp");
 25             // 取Pixbuf第一个点的rgb值
 26             byte r, g, b;
 27             unsafe {
 28                 // Pixbuf的Pixels未记录图片每个点信息值
 29                 // 取(x,y)的rgb值,以下代码中x,y均为0
 30                 // var p = (byte*)pixbufO.Pixels.ToPointer() + y * pixbufO.Rowstride + x * pixbufO.NChannels;
 31                 var p = pixbufO.Pixels.ToPointer();
 32                 r = *(byte*)p;
 33                 g = *((byte*)p + 1);
 34                 b = *((byte*)p + 2);
 35             }
 36             // 依据第一个点的rgb值增加透明通道
 37             var pixbuf = pixbufO.AddAlpha(true, r, g, b);
 38 
 39             Decorated = false;      // 不设置窗体边框
 40             AppPaintable = true;    // 应用程序绘制界面
 41             SetDefaultIconFromFile("Clock00.ico");
 42             //SetDefaultSize(pixbuf.Width, pixbuf.Height);
 43             SetDefaultSize(500500);
 44             SetPosition(WindowPosition.Center);
 45 
 46             Realize();      // 创建Window的资源,若不调用则this.GdkWindow为null
 47 
 48             DeleteEvent += delegate { Application.Quit(); };
 49             // 添加鼠标点击事件
 50             AddEvents((int)EventMask.ButtonPressMask);
 51             GLib.Timeout.Add(100, OnTimer);     // 时间事件
 52 
 53             Pixmap pixmap, pixmask;
 54             // 依据Pixbuf创建Pixmap以及对应的蒙板Pixmap
 55             pixbuf.RenderPixmapAndMask(out pixmap, out pixmask, 128);
 56             ShapeCombineMask(pixmask, 00);
 57             GdkWindow.SetBackPixmap(pixmap, false);
 58 
 59             ShowAll();
 60         }
 61 
 62         protected override bool OnButtonPressEvent(EventButton evnt)
 63         {
 64             // 鼠标左键点击移动窗体
 65             if (evnt.Type == EventType.ButtonPress && evnt.Button == 1) {
 66                 BeginMoveDrag((int)evnt.Button, (int)evnt.XRoot, (int)evnt.YRoot, evnt.Time);
 67             }
 68             return base.OnButtonPressEvent(evnt);
 69         }
 70 
 71         protected override bool OnExposeEvent(EventExpose evnt)
 72         {
 73             base.OnExposeEvent(evnt);
 74 
 75             using (var cr = CairoHelper.Create(evnt.Window)) {
 76                 var curTime = DateTime.Now;
 77                 int tenDigit, entriesDigit;
 78 
 79                 var x = 25;
 80                 const int y = 80;
 81                 cr.Save();
 82                 // 绘制左侧空白
 83                 cr.Translate(x, y);
 84                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -(15 * 10 + 8), 0);
 85                 cr.Rectangle(00225);
 86                 cr.Clip();
 87                 cr.Paint();
 88                 
 89 
 90                 // HH
 91                 DecToBcd(curTime.Hour, out tenDigit, out entriesDigit);
 92                 x += 2;
 93                 cr.Restore();
 94                 cr.Save();
 95                 cr.Translate(x, y);
 96                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * tenDigit, 0);
 97                 cr.Rectangle(001525);
 98                 cr.Clip();
 99                 cr.Paint();
100 
101                 x += 15;
102                 cr.Restore();
103                 cr.Save();
104                 cr.Translate(x, y);
105                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * entriesDigit, 0);
106                 cr.Rectangle(001525);
107                 cr.Clip();
108                 cr.Paint();
109 
110                 // :
111                 x += 15;
112                 cr.Restore();
113                 cr.Save();
114                 cr.Translate(x, y);
115                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * 100);
116                 cr.Rectangle(00825);
117                 cr.Clip();
118                 cr.Paint();
119 
120                 // MM
121                 DecToBcd(curTime.Minute, out tenDigit, out entriesDigit);
122                 x += 8;
123                 cr.Restore();
124                 cr.Save();
125                 cr.Translate(x, y);
126                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * tenDigit, 0);
127                 cr.Rectangle(001525);
128                 cr.Clip();
129                 cr.Paint();
130 
131                 x += 15;
132                 cr.Restore();
133                 cr.Save();
134                 cr.Translate(x, y);
135                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * entriesDigit, 0);
136                 cr.Rectangle(001525);
137                 cr.Clip();
138                 cr.Paint();
139 
140                 // :
141                 x += 15;
142                 cr.Restore();
143                 cr.Save();
144                 cr.Translate(x, y);
145                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * 100);
146                 cr.Rectangle(00825);
147                 cr.Clip();
148                 cr.Paint();
149 
150                 // SS
151                 DecToBcd(curTime.Second, out tenDigit, out entriesDigit);
152                 x += 8;
153                 cr.Restore();
154                 cr.Save();
155                 cr.Translate(x, y);
156                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * tenDigit, 0);
157                 cr.Rectangle(001525);
158                 cr.Clip();
159                 cr.Paint();
160 
161                 x += 15;
162                 cr.Restore();
163                 cr.Save();
164                 cr.Translate(x, y);
165                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -15 * entriesDigit, 0);
166                 cr.Rectangle(001525);
167                 cr.Clip();
168                 cr.Paint();
169 
170                 // 绘制右侧空白
171                 x += 15;
172                 cr.Restore();
173                 cr.Save();
174                 cr.Translate(x, y);
175                 CairoHelper.SetSourcePixbuf(cr, _pixbufNumber, -(15 * 10 + 8), 0);
176                 cr.Rectangle(00225);
177                 cr.Clip();
178                 cr.Paint();
179 
180                 cr.Restore();
181             }
182 
183             return true;
184         }
185 
186         bool OnTimer()
187         {
188             if (!timer) return false;
189 
190             QueueDraw();
191             return true;
192         }  
193 
194         // 依据两位数获取该数字的十位、个位数
195         private static void DecToBcd(int decimalNum, out int tenDigit, out int entriesDigit)
196         {
197             tenDigit = decimalNum / 10;
198             entriesDigit = decimalNum % 10;
199         }
200     }
201 }

 主窗体背景图片:

 

时钟数字图片:

 

程序运行图片:

posted on 2011-09-30 16:00 山伟 阅读(...) 评论(...) 编辑 收藏