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...