我也学写天气预报。。。
作为一个不务正业,在工作至于业余自学 delphi 的人,看到 VC 版本有说模拟 QQ 的外观的帖子,额,那个,我在 delphi 板块也学写一个天气秀。
先来看看结果的截图:
首先,准备好如下东西:
1.delphi2010, 听说那个叫“易博龙”的网站有下载,非免费。。。
2.GDIplus,你可以去 http://www.progdigy.com/ 下载,开源免费。
3.素材,我用 Fireworks 做了个,功底不好,不要见笑;
这是天气图片:
这是背景图:
先说下大概原理,其实就将需要的图片合成,然后在合成结果上面画上字,将这个最后合成的图作为窗体背景。一般用 Bitmap 位图的就不说,到处都有。这次只要是用 Png 图片作为窗体背景,处理 PNG 时候是用 GDI+ 来处理,就是这么简单。
好了,下面开始动工。
1.
先新建一个 VCL Form 应用工程;然后在引用单元手动输入以下几个单元:
GDIPUTIL, GDIPAPI, GDIPOBJ, {GDI+ 需要}pngimage, {PNG 需要}ActiveX;{内存流需要}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;
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;{过程名程: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;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);begin ReleaseCapture; Perform(WM_SYSCOMMAND, $F012, 0);end;
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;procedure TForm1.MnuClose1Click(Sender: TObject);begin Close { 886 }end;
[解决办法]
支持下,不错,,顶。。呵呵
[解决办法]
强 啊 牛逼
[解决办法]
做得挺不错啊~!
[解决办法]
收藏 先。
高人勒
[解决办法]
[解决办法]
很好看
[解决办法]
高人啊
[解决办法]
Mark!!!!!
[解决办法]
LZ
顶
[解决办法]
收藏之,虽然不会Delphi。
[解决办法]
顶贴,学习
[解决办法]
顶,学习学习
[解决办法]
学习一下
[解决办法]
学习一下了
[解决办法]
学习了,不错,要顶。
[解决办法]
原创的好贴
[解决办法]
支持.......
[解决办法]
用高版本的,可以直接画PNG,而且代码少,用不着GDI+
[解决办法]
顶贴
[解决办法]
很好,很好,谢谢楼主分享。
[解决办法]
学习学习。。
谢谢分享。。
[解决办法]
很好,很强大。
[解决办法]
帅,谢谢分享
[解决办法]
转一转。。。。
[解决办法]
不错 就是不会 用什么软件呢?
[解决办法]
虽然不懂delphi,但还是顶一下
[解决办法]
谢谢楼主分享。..
[解决办法]
CSDN里象楼主这么细心认真并且愿意分享自己知识的人,实在是太少了。赞一个先。
[解决办法]
收藏 先。
[解决办法]
我晕 还挺像win7 的
[解决办法]
高手,顶
[解决办法]
这个不懂,但是觉得挺好的