今天开始, 所有的技术文尽量全部用e 文! @@

I don’t really know the exact difference between “transparency” and “translucency”. But the flowing pictures of my running application may show you.

Pic-1 shows a normal dialog with gradient background filled. Pic-2 add opacity ability to the whole dialog(transparent). While Pic-3 only add opacity to the dialog’s background(per-pixel, translucency).

If you’re using windows sdk, there’s an API called “SetLayeredWindowAttributes” to realize the function in Pic-2. You can also call it with a transparency color key to make all pixels of this color to be transparent. But, how to realize the function in Pic-3? My dialog’s background is in gradient color. As mentioned here(in Chinese): To realize it, you must use an API called “UpdateLayeredWindow”. And it’s quite troublesome.

There are also GUI libraries to fill this requirements: 1) WPF, 2) Qt. My application is written in Qt. How do WPF and Qt implement this feature? By drawing all controls themselves. They do not use native windows controls. So if you do it yourself, what a big project !

Using Qt, I call QWidget::setWindowOpacity() to set whole transparency of a window(Pic-2). Qt 4.5 is just released. There’s a new translucency attribute in QWidget class. I use it to realize per-pixel alpha blending(Pic-3). Here’s Sample code:

The demo project can be found here. Note:
a) Make sure you have Qt 4.5 installed to build the project.
b) The translucent window’s type should be set to Qt::FramelessWindowHint.

额.. 又漏了…

这次是GDI+ 的调用引起的, 看代码吧:

主要问题在于Graphics 那个对象. 实际上当前代码的SelectObject() 调用是错误的, 结果就是HBITMAP 对象又泄漏了. 解决的办法就是Graphics 对象用完了就删掉, 就不会锁住里面的HBITMAP 对象了. 方法有2 种: 1) 加一个作用域, 就是把上面的注释去掉. 2) new 一个Graphics 对象, 用完了直接delete 掉.

发现GDI+ 虽然封装了一些比较好用的函数, 但是很容易出错, 而且performance 也不太好. 以后还是少用为妙.

第一篇技术文…

内存泄漏, 句柄泄漏.. windows 编程中最头痛的事情. windows 提供了查看内存检测内存泄漏的API, 却没有提供检测句柄的, 至少我不知道. 第三方的工具如BoundsChecker 倒是异常强大.实在不行并且看得懂nc 堆栈信息的话, 可以用用看M$自家的 AppVerifier .

今天碰到的问题很诡异. 在用工具检查完GDI 句柄泄漏之后, 跑了一上午某个绘图程序, 内存居然涨到了100+M, ft 啊. 于是代码一段段注掉, 找到底哪里漏了… 最后定位到这样的一段代码:

问题在于, 最后的DeleteObject() 调用不正确. 应改为如下:

就是说, 一个HBITMAP 跟一个HDC 还有关联的时候, 不要调用DeleteObject(), 而应该先把原始的HBITMAP 句柄SelectObject() 还原回去. 有以下几条notes:

  • Bitmaps must be disconnected from a DC before being freed.
  • Menus must be freed before an application exits if the menu is not connected to any window.
  • A DC must be disconnected from bitmaps before being freed.
  • If a bitmap is specified for the Caret, it must be freed.
  • Calls to DeleteObject do not harm stock objects.

深愛
水樹奈々

雪が舞い散る夜空
二人寄り添い見上げた
繋がる手と手の温もりは とても優しかった

淡いオールドブルーの
雲間に消えて行くでしょう
永遠へと続くはずの あの約束

あなたの側にいるだけで
ただそれだけでよかった
いつの間にか膨らむ
今以上の夢に気付かずに

どんな時も どこにいる時でも
強く強く抱きしめていて
情熱が日常に染まるとしても
あなたへのこの想いはすべて
終わりなどないと信じている
あなただけずっと見つめているの

交わす言葉と時間
姿も変えて行くでしょう
白い頬に溶けたそれは 月の涙

行かないで もう少しだけ
何度も言いかけては
また会えるよねきっと
何度も自分に問いかける

突然走り出した
行く先の違う二人
もう止まらない
沈黙が想像を越え引き裂いて
一つだけ許される願いがあるなら
ごめんねと伝えたいの

いくら思っていても届かない
声にしなきゃ 動き出さなきゃ
隠したままの二人の秘密
このまま忘れられてしまうの
だからね早く 今ここに来て

あなたの側にいるだけで
ただそれだけでよかった
今度巡り会えたら
もっともっと笑いあえるかな?

どんな時も どこにいる時でも
強く強く抱きしめていて
情熱より熱い熱で溶かして
あなたへのこの想いはすべて
終わりなどないと信じている
あなただけずっと見つめているの

深愛
水樹奈奈

雪花飞舞的夜空
我们两人并肩仰望
紧系著的手和手的温暖 非常的和善

在淡薄蔚蓝的
云彩间隙裏消逝了的吧
本应该永远持续的 那个约定

只要守候在你的身边
仅仅如此就心满意足了
不知何时已膨胀起
穿越现实的梦而我却没有察觉

无论身处何时人在何方
我们都能紧紧的互相拥抱
尽管这份热情将生命映的火红
对於你的这个感情就是一切
并坚信著不会有终结的一天
仅仅只有你是我一直想要注视的

交錯的說話與時間
形貌都會改變
在雪白的臉頰上溶化的 月亮的眼淚

請不要走 多留一會吧
無數次欲言又止
一定會再相見吧
無數次自問

突然踏上路途
目的地不同的兩人
已經無法阻止
沉默超越想像
如果只能實現一個願望
想跟你說對不起

單是心裏想 怎樣也不能傳達
要說出口 要行動
再這樣下去
兩人之間隱藏的秘密就要被忘掉
所以請你現在快點來這裏

只要守候在你的身边
仅仅如此就心满意足了
下次跟你碰面的時候
可以相視而笑嗎?

無論何時 無論身處何地
都想你緊緊抱着我
溶掉比熱情更熾熱的熱度
對你的思念就是一切
至今仍相信不會終結
只想永遠注視你