读书人

小弟我也学写天气预报。

发布时间: 2012-03-12 12:45:33 作者: rapoo

我也学写天气预报。。。
作为一个不务正业,在工作至于业余自学 delphi 的人,看到 VC 版本有说模拟 QQ 的外观的帖子,额,那个,我在 delphi 板块也学写一个天气秀。


先来看看结果的截图:

首先,准备好如下东西:
1.delphi2010, 听说那个叫“易博龙”的网站有下载,非免费。。。
2.GDIplus,你可以去 http://www.progdigy.com/ 下载,开源免费。
3.素材,我用 Fireworks 做了个,功底不好,不要见笑;
这是天气图片:

这是背景图:


先说下大概原理,其实就将需要的图片合成,然后在合成结果上面画上字,将这个最后合成的图作为窗体背景。一般用 Bitmap 位图的就不说,到处都有。这次只要是用 Png 图片作为窗体背景,处理 PNG 时候是用 GDI+ 来处理,就是这么简单。

好了,下面开始动工。
1.
先新建一个 VCL Form 应用工程;然后在引用单元手动输入以下几个单元:

Delphi(Pascal) code
GDIPUTIL, GDIPAPI, GDIPOBJ, {GDI+ 需要}pngimage, {PNG 需要}ActiveX;{内存流需要}

再拖一个 PopupMenu 上去,建两条项目:
一条 Caption 为 Close, 关闭程序用;
一条 Caption 为 About, 这个干嘛用?下面的同学说一下。。。
设置主窗体的 PopupMenu 为刚才拖下来的 PopupMenu1.

2.
定义一个类型:为下面 IStream / TStream 转换需要。
Delphi(Pascal) code
type  TFixedStreamAdapter = class(TStreamAdapter)  public    function Stat(out statstg: TStatStg; grfStatFlag: Longint): HResult;      override; stdcall;  end;function TFixedStreamAdapter.Stat(out statstg: TStatStg;  grfStatFlag: Integer): HResult;begin  Result := inherited Stat(statstg, grfStatFlag);  statstg.pwcsName := nil;end;


3.
使用 GDI+ 合成图片:
先看看需要的子过程:
Delphi(Pascal) code
procedure DrawBkgroud; { 合成图片的过程 }具体实现如下:procedure TForm1.DrawBkgroud;var  Bg: TGPBitmap;  G: TGPGraphics;  Guid: TGUID;  WD: TGPBitmap;  Cav: TGPBitmap;  Png: TPngImage;  MS: TMemoryStream;  FontFamily: TGPFontFamily;  LFont, SFont: TGPFont; { 字体 }  LPointF, SPointF: TGPPointF;  LSolidBrush, SSolidBrush: TGPSolidBrush;begin  Png := TPngImage.CreateBlank(COLOR_RGBALPHA, 16, 359, 272); { 创建指定大小 359 * 272 空白的png }  {有同学会问 那个 359,272 是怎么得到的呢?额,根据背景图片大小自己写的。。。 }  Png.SaveToFile('png_out.png'); { 测试保存,结果是一个带 Alpha 通道的空白 PNG }  MS := TMemoryStream.Create;  Png.SaveToStream(MS);{ 保存到内存流,待用 }  Png.Free;  Bg := TGPBitmap.Create('bg.png'); { 载入背景图片 }  WD := TGPBitmap.Create('0.png'); { 载入天气状况图片 }  Cav := TGPBitmap.Create(TFixedStreamAdapter.Create(MS)); { 从内存流创建窗体背景图 }  MS.Free;  G := TGPGraphics.Create(Cav);{ 开始合成 }  FontFamily := TGPFontFamily.Create('Tahoma');  LFont := TGPFont.Create('Tahoma', 20, FontStyleBold, UnitPixel); { 大字体 }  SFont := TGPFont.Create('微软雅黑', 15, FontStyleBold, UnitPixel); { 小字体 }  LSolidBrush := TGPSolidBrush.Create(MakeColor(26, 161, 245));{ 字体颜色 }  SSolidBrush := TGPSolidBrush.Create(MakeColor(240, 240, 240));  G.DrawImage(Bg, 30, 30);  G.DrawImage(WD, 0, 0);  LPointF := MakePoint(130.0, 60.0);{ 位置 }  G.DrawString('25~32℃', -1, LFont, LPointF, LSolidBrush);  SPointF := MakePoint(130.0, 98.0);  G.DrawString('晴转阴,间中有钱掉下', -1, SFont, SPointF, SSolidBrush);  SPointF := MakePoint(130.0, 120.0);  G.DrawString('微风,风力 18 级', -1, SFont, SPointF, SSolidBrush);  { 测试存为 png ... }  GetEncoderClsid('image/png', Guid);  Cav.Save('out.png', Guid);{ 看看合成结果呗 }  RenderForm(220, Cav); { 将窗体设置为靓靓背景吧。。。}  Cav.Free;  WD.Free;  G.Free;  Bg.Free;end;


4.
既然上面已经使用了个过程 RenderForm(220, Cav),现在继续完成它。
Delphi(Pascal) code
{过程名程:RenderForm(透明度,窗体背景图)}procedure RenderForm(TransparentValue: Byte; SourceImage: TGPBitmap);procedure TForm1.RenderForm(TransparentValue: Byte; SourceImage: TGPBitmap);var  zsize: TSize;  zpoint: TPoint;  zbf: TBlendFunction;  TopLeft: TPoint;  WR: TRect;  GPGraph: TGPGraphics;  m_hdcMemory: HDC;  hdcScreen: HDC;  hBMP: HBITMAP;  FDC: HDC;begin  hdcScreen := GetDC(0);  m_hdcMemory := CreateCompatibleDC(hdcScreen);  hBMP := CreateCompatibleBitmap(hdcScreen, SourceImage.GetWidth(),    SourceImage.GetHeight());  SelectObject(m_hdcMemory, hBMP);  GPGraph := TGPGraphics.Create(m_hdcMemory);  try    { GPGraph.SetInterpolationMode(InterpolationModeHighQualityBicubic); }    GPGraph.DrawImage(SourceImage, 0, 0, SourceImage.GetWidth(),      SourceImage.GetHeight());    SetWindowLong(Handle, GWL_EXSTYLE,      GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED); { 这个必须有 }    zsize.cx := SourceImage.GetWidth;    zsize.cy := SourceImage.GetHeight;    zpoint := Point(0, 0);    with zbf do    begin      BlendOp := AC_SRC_OVER;      BlendFlags := 0;      AlphaFormat := AC_SRC_ALPHA;      SourceConstantAlpha := TransparentValue;    end;    GetWindowRect(Handle, WR);    TopLeft := WR.TopLeft;    { UpdateLayeredWindow(Handle, FDC, @TopLeft, @zsize, GPGraph.GetHDC, @zpoint,     0, @zbf, ULW_ALPHA); WIN7 里面可以,WINXPSP3 就不行。。。所以改为以下:}    UpdateLayeredWindow(Handle, 0, nil, @zsize, GPGraph.GetHDC, @zpoint, 0,      @zbf, ULW_ALPHA);  finally    GPGraph.ReleaseHDC(m_hdcMemory);    ReleaseDC(0, hdcScreen);    DeleteObject(hBMP);    DeleteDC(m_hdcMemory);    GPGraph.Free;  end;end; 



4.
啊?发现一切如愿都出来的,但是不能拖动窗体到处走。。。老生长谈的东西。
Delphi(Pascal) code
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;  Shift: TShiftState; X, Y: Integer);begin  ReleaseCapture;  Perform(WM_SYSCOMMAND, $F012, 0);end;


5.
继续继续,可是没东西可写了,好吧,就写个 About 。。。
Delphi(Pascal) code
procedure TForm1.MnuAboutClick(Sender: TObject);begin  Application.MessageBox    ('模拟天气预报,GDI+ 实现。' + #13#10 +      'email: sail2000#126.com' + #13#10 + '2010/09/10, 小帆, 广州', '关于',    MB_OK + MB_ICONINFORMATION);end;


6.
额,原来如此简单,知道了吧,知道了,就应该写最后一句了:
Delphi(Pascal) code
procedure TForm1.MnuClose1Click(Sender: TObject);begin  Close { 886 }end;


最后,我是业余自学 Delphi 的,很多东西不知道原理,只知道这样用而用。
下面肯定有同学会问:咦?结果是出来的,但是不能再往窗体上放控件了!
对,这个事情,我曾经也问过外国的 delphi 技术高手,
那老头说:方法有二:
1.改用底层重写窗体。
2.用两个窗体搭配。。。(天气秀之类的就是这样实现的!!!)

好了,就这样了。


[解决办法]
好贴 顶之
[解决办法]

[解决办法]

[解决办法]
果断顶贴。。!
[解决办法]

[解决办法]
不错啊,支持
[解决办法]
强啊!!!
[解决办法]
不错,收藏之,不知道楼主用delphi2010感觉怎么样
[解决办法]
不错!
[解决办法]
感谢小帆的分享
[解决办法]
支持一下。。。。。。。。。。
[解决办法]
膜拜楼主
[解决办法]
有想法。
[解决办法]
虽然我没学Delphi,但帖子不错
[解决办法]
果断顶!!!!!!!!!!!!
[解决办法]
好贴,想不到还有如此delphi粉丝
[解决办法]
不错嘛这个
[解决办法]
自学!精神可嘉!
[解决办法]
有点意思
[解决办法]
很牛,很牛


[解决办法]
i think it could be better
[解决办法]
每天回帖即可获得10分可用分!小技巧:教您如何更快获得可用分
[解决办法]
很强大


[解决办法]
支持下,不错,,顶。。呵呵
[解决办法]
强 啊 牛逼
[解决办法]
做得挺不错啊~!
[解决办法]
收藏 先。
高人勒
[解决办法]

[解决办法]
很好看
[解决办法]
高人啊
[解决办法]
Mark!!!!!
[解决办法]
LZ


[解决办法]
收藏之,虽然不会Delphi。
[解决办法]
顶贴,学习

[解决办法]
顶,学习学习
[解决办法]
学习一下
[解决办法]
学习一下了
[解决办法]
学习了,不错,要顶。
[解决办法]
原创的好贴
[解决办法]
支持.......
[解决办法]
用高版本的,可以直接画PNG,而且代码少,用不着GDI+
[解决办法]
顶贴
[解决办法]
很好,很好,谢谢楼主分享。
[解决办法]
学习学习。。
谢谢分享。。
[解决办法]
很好,很强大。
[解决办法]
帅,谢谢分享
[解决办法]
转一转。。。。
[解决办法]
不错 就是不会 用什么软件呢?

[解决办法]
虽然不懂delphi,但还是顶一下
[解决办法]
谢谢楼主分享。..

[解决办法]
CSDN里象楼主这么细心认真并且愿意分享自己知识的人,实在是太少了。赞一个先。
[解决办法]
收藏 先。

[解决办法]
我晕 还挺像win7 的
[解决办法]
高手,顶
[解决办法]
这个不懂,但是觉得挺好的

读书人网 >.NET

热点推荐