VB6給MDI視窗 父視窗 動態繪製背景的種種方法

2021-06-17 23:37:33 字數 3599 閱讀 5152

vb6就不說了,要快速寫乙個程式,.net(c#)可能還更好更強大,但是要說安全,vb6反到強過他們

有時候兩者就是一種矛盾,所以越是使用者友好,越是易維護和擴充套件的程式,越容易被破解.

mdi視窗沒有refresh方法,沒有paint事件,沒有hdc,更沒有paintpicture方法.等等,我們先說動態繪製的必要性.

mdi父視窗有個picture屬性,可以載入一幅影象,然而動態繪製可以根據視窗的大小調整背景.

不要告訴我,你要做width * height張,每次都用loadpicture,那你的程式還真是大系統了...

由於上面所說的mdi窗體的限制,常規的方法是不行了,現在先提供乙個笨一點的方法,越笨越實用,也越簡單

1.用picturebox繪製好

public sub draw1(mf as mdiform, sp as stdpicture, p as picturebox)

p.scalemode = vbpixels

p.width = mf.scalewidth '注意單位

p.height = mf.scaleheight '注意單位

p.autoredraw = true

p.paintpicture sp, 0, 0, p.scalewidth, p.scaleheight

mf.picture = p.picture

mf.backcolor = vbwhite 'force refresh

end sub

首先要注意的是picturebox的容器scalemode會對度量有影響,關鍵後面要賦值背景色,這樣會強迫mdi窗體重繪,當然覆蓋背景色,就實現了

調整paintpicture的引數可以實現居中,平鋪(縮放)等等各種效果

但是限制是需要乙個picturebox控制項,該控制項放到mdi中會觸動align屬性,即使隱藏了,設計的時候也很**觀,人愛面子樹愛皮,程式愛ui

所以,必須加乙個picturebox,往往要加乙個form.能不能把picturebox封裝到類中呢?我覺得應該可以,甚至可以

private withevents m_draw as picturebox
只是到現在我還沒實現出來.

那麼,還有沒有其他替代方案呢,當然,picturebox最重要的屬性是picture,是乙個ipicturedisp(stdpicture),而paintpicture方法就是

對stdpicture的render方法封裝.只是render方法原圖形的度量是按himetric算的,要經過換算,用render方法可以直接渲染到dc上

2.待研究的render方法,常規的form是沒問題,如

option explicit

dim p as stdpicture

private sub form_load()

me.scalemode = vbpixels

'me.autoredraw = true

set p = loadpicture("f:\codes\vbcode\1.bmp")

end sub

private sub form_resize()

p.render me.hdc, 0, 0, me.scalewidth, me.scaleheight, 0, p.height, p.width, -p.height, byval 0

end sub

private sub form_unload(cancel as integer)

set p = nothing

end sub

但是注意的一點是,mdi窗體沒有hdc,那怎麼辦,對api直接取dc,如:

hdc1 = getdc(mf.hwnd)

call getclientrect(mf.hwnd, rc)

p.render hdc1, 0, 0, rc.right - rc.left, rc.bottom - rc.top, 0, p.height, p.width, -p.height, byval 0

mf.backcolor = &hf0f0f7 '.refresh

call releasedc(mf.hwnd, hdc1)

然而,問題來了,提示無效引數,毛啊!用spy++,發現mdi窗體的客戶區其實是vb自己建立的乙個子視窗(ws_child),其類名是mdiclient

那麼我們修改一下,而且用getwindowdc代替成對的getdc,如下

hclient = findwindowex(mf.hwnd, 0, "mdiclient", vbnullchar)

call getclientrect(hclient, rc)

hdc1 = getwindowdc(hclient)

p.render hdc1, 0, 0, rc.right - rc.left, rc.bottom - rc.top, 0, p.height, p.width, -p.height, byval 0

mf.backcolor = &hf0f0f7 '.refresh

問題依舊,沒辦法了,目前來說,暫時委屈一下吧,難道我們天生就是奴隸?

vb很像乙個東西,那就mfc類庫,其實都是對windows api的封裝,那麼其最終的實現都是api呼叫,那麼就想到另外一招:

3.無敵的記憶體繪圖

public sub draw1(mf as mdiform, p as stdpicture)

dim hclient as long, hold as long

dim hdc1 as long, hdc2 as long

dim rc as rect

hclient = findwindowex(mf.hwnd, 0, "mdiclient", vbnullchar)

call getclientrect(hclient, rc)

hdc1 = getwindowdc(hclient)

hdc2 = createcompatibledc(hdc1)

hold = selectobject(hdc2, p.handle)

bitblt hdc1, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdc2, 0, 0, vbsrccopy

selectobject hdc2, hold

deletedc hdc2

'p.render hdc1, 0, 0, rc.right - rc.left, rc.bottom - rc.top, 0, p.height, p.width, -p.height, byval 0

mf.backcolor = &hf0f0f7 '.refresh

end sub

調整bitblt的引數,就跟調整paintpicture的引數一樣簡單,說白了paintpicture最終還是封裝了bitblt,當然你可以使用其他的繪圖api,甚至直接操作點陣圖的畫素

但是那樣的投入就太大了,一開始我還想用c/c++寫個動態庫,那樣可能效率高點,但是犧牲開發效率來換取執行效率,不見得是明智的選擇.

這是我研究出最卑鄙無恥下流銀劍的方法了.

VB6技巧 總結

vb設定多行textbox的位置 由於自動輸入的文字比較多,最後輸入的跑到下面了,想要自動滾動到下面,本來以為 操作滾動條呢,但是沒有方法。於是我巧妙的採用了 顯示列表是設定了乙個多行 的 textbox 顯示列表.selstart len 顯示列表.text 1 顯示列表.sellength 1 ...

vb6 讀寫檔案

write file dim nhandle as integer,fname as string fname d 1.txt nhandle freefile open fname for output as nhandle print nhandle,0 print nhandle,2 clos...

VB6 系統列印常識

在一次做列印的時候,對位置的調整老是不得法,後來通過cbm666老師的幫助才解決問題,分享以下他給的幫助。其中pic 為物件,如圖形框picture等 destx,desty 目標影象位置 destwidth,destheight 目標影象尺寸 scrx,scry 原影象的裁剪座標 scrwidth...