国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

VB.net基礎:簡單的自定義控件MyPictureBox

2024-07-10 13:01:04
字體:
來源:轉載
供稿:網友
先說明一下,有的代碼行比較長所以不容易看清。建議先粘貼到vs.net中,這樣好看一點。


這里標題中的“簡單”,并不是說代碼簡單,而是說思路比較簡單。vs.net中的picturebox有個缺點就是不好控制位置和大小。所以mypicturebox就是這樣一種picturebox:它有一個屬性viewmode,表示顯示圖片的模式,包括fitsize,truesize和stretchimage。后兩者看名字也看得出意思來,fitsize則是一個折中的方式:當圖片大小小于mypicturebox大小的時候,不進行圖片縮放。還有,mypicturebox自動將圖片放到中間,當其大小改變的時候也能保持圖片在mypicturebox的中間。另外,當圖片大小大于mypicturebox大小的時候,用戶能夠像photoshop的手形工具那樣“拖動”圖片以方便瀏覽??傊?,我們的mypicturebox就這三大特點。



首先,以“windows控件庫”建立一個新工程,將一個picturebox拖到用戶控件上。界面就ok了。

然后我們要定義viewmode。先建立一個enum:
public enum vmode
fitsize = 0
stretchimage = 1
truesize = 2
end enum

然后建立一個變量存放viewmode屬性:
private vviewmode as vmode = vmode.truesize

當viewmode變化的時候,控件有必要向外界發出一個事件:
public event viewmodechanged(byval mode as vmode)

現在可以寫viewmode屬性了:
public property viewmode() as vmode
get
return vviewmode
end get
set(byval value as vmode)
dim changed as boolean = false
if value <> vviewmode then changed = true
vviewmode = value
if changed then showpic()
raiseevent viewmodechanged(value)
end set
end property

這里,showpic()是尚未定義的方法,作用就是顯示圖片。
另外,既然是mypicturebox,那就要有picturebox的樣。所以要加上一個image屬性:
public property image() as image
get
return picturebox1.image
end get
set(byval value as image)
if value is nothing then '判斷一下value是不是空值。
picturebox1.borderstyle = borderstyle.none
exit property
else
picturebox1.borderstyle = borderstyle.fixedsingle
end if
value = new bitmap(value)
picturebox1.sizemode = pictureboxsizemode.stretchimage
picturebox1.image = value
imagerate = value.width / value.height
showpic()
end set
end property

這里imagerate是為了避免重復計算的開銷的定義的一個變量,用來存儲圖像的寬高比,類型是single??梢栽谇懊婕由纤亩x。
現在我們來寫showpic。為了代碼結構分明,showpic內容很簡單:
private sub showpic()
if picturebox1.image is nothing then exit sub
if picturebox1.visible = false then picturebox1.visible = true
resizeimage()
end sub

之所以要把resizeimage單獨寫開來是因為這部分還有其他地方要重用。resizeimage的作用是根據當前的viewmode值,來改變picturebox1的sizemode屬性,并決定是否對圖片進行縮放:
private sub resizeimage()
if picturebox1.image is nothing then exit sub

if vviewmode = vmode.fitsize then
if picturebox1.image.width > me.width or picturebox1.image.height > me.height then
stretchimage()
else
if not picturebox1.sizemode = pictureboxsizemode.autosize then picturebox1.sizemode = pictureboxsizemode.autosize
end if
elseif vviewmode = vmode.stretchimage then
stretchimage()
else
if not picturebox1.sizemode = pictureboxsizemode.autosize then picturebox1.sizemode = pictureboxsizemode.autosize
end if

locateimage()
end sub

這一段判斷有些復雜,其實應該可以寫得更好一點的。stretchimage和locateimage的作用從名字上大概就能看出來了。先看看stretchimage。它是真正縮放圖片的方法。其實也不復雜:
private sub stretchimage()
picturebox1.sizemode = pictureboxsizemode.stretchimage
if merate < imagerate then
picturebox1.width = me.width
picturebox1.height = picturebox1.width / imagerate
else
picturebox1.height = me.height
picturebox1.width = picturebox1.height * imagerate
end if
end sub

這里merate用來保存mypicturebox本身的寬高比。類型是single,現在可以在前面加上它的定義。顯然,strechimage實際上就是改變picturebox1的寬高。計算好圖片框的大小之后,要保持圖片在中間,需要計算圖片框的位置。locateimage就是作這個用的:
private sub locateimage()
if picturebox1.width < me.width then
picturebox1.left = (me.width - picturebox1.width) / 2
else
picturebox1.left = 0
end if

if picturebox1.height < me.height then
picturebox1.top = (me.height - picturebox1.height) / 2
else
picturebox1.top = 0
end if
end sub

當mypicturebox大小改變的時候,圖片的大小和位置就要重新計算。沒錯,應該寫在resize事件里面。不過且慢。如果不加控制的話,在用戶拖動改變mypicturebox大小的過程中,因為不停的計算圖片的大小和位置,cpu的占用率會達到100%。這是很不友好的,甚至可以用“霸道”來形容。也許我們應該開一個線程,在線程當中用sleep來避免這種情況。但是這寫起來又太復雜了點。所以我們用timer這種折中的辦法?;氐皆O計器視圖,拖過來一個timer。設置interval值為25。在timer1_tick當中寫上:
private sub timer1_tick(byval sender as system.object, byval e as system.eventargs) handles timer1.tick
if vviewmode = vmode.stretchimage or vviewmode = vmode.fitsize then
resizeimage()
else
locateimage()
end if
timer1.stop()
end sub

然后再在resize事件中寫上:
private sub mypicturebox_resize(byval sender as object, byval e as system.eventargs) handles mybase.resize
merate = me.width / me.height
timer1.start()
end sub

這樣的組合就能達到目標了。

然后我們再寫“拖動”圖片的功能。顯然,這個功能只有當viewmode=truesize的時候才有用。這個功能分三部分,首先是mousedown事件:
private sub picturebox1_mousedown(byval sender as object, byval e as system.windows.forms.mouseeventargs) handles picturebox1.mousedown
if e.button <> mousebuttons.left or viewmode <> vmode.truesize then exit sub
moving = true
me.cursor = system.windows.forms.cursors.hand
mousepos = me.mouseposition
oldscroll = me.autoscrollposition
end sub

這里moving變量用來表示用戶是否正在拖動圖片,類型是boolean。沒定義?到前面去定義一下不就行了。還有什么mousepos,oldscroll,它們倆的類型是point??烊ザx一下。當用用戶按下鼠標左鍵的時候,記錄下鼠標位置和圖片當的前滾動位置。

然后是mousemove事件:

等等。在用戶移動鼠標的時候,又要不停的計算圖片框的滾動位置。為了避免再次“霸道”起來,我們又要拖進來一個timer。設置interval值為1。這個timer是這樣的:
private sub timer2_tick(byval sender as system.object, byval e as system.eventargs) handles timer2.tick
mouseposnow = me.mouseposition
dim deltapos as point = new point((mousepos.x - mouseposnow.x), (mousepos.y - mouseposnow.y))
me.autoscrollposition = new point(-oldscroll.x + deltapos.x, -oldscroll.y + deltapos.y)
timer2.stop()
end sub

就四句話,應該不太難看懂吧。
所以mousemove就這樣:
private sub picturebox1_mousemove(byval sender as object, byval e as system.windows.forms.mouseeventargs) handles picturebox1.mousemove
if moving then
timer2.start()
end if
end sub

第三部分就是mouseup事件了,就兩句話:
private sub picturebox1_mouseup(byval sender as object, byval e as system.windows.forms.mouseeventargs) handles picturebox1.mouseup
moving = false
me.cursor = system.windows.forms.cursors.default
end sub

這樣,mypicturebox就寫好了。





……沒錯,是寫好了。運行一下看看。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 泰安市| 绥芬河市| 上高县| 新邵县| 宝应县| 金塔县| 百色市| 新干县| 崇信县| 依兰县| 建阳市| 偃师市| 游戏| 泸州市| 阿拉尔市| 光泽县| 孙吴县| 佛学| 义乌市| 清丰县| 渝北区| 微山县| 吉安市| 阿城市| 久治县| 四平市| 仁布县| 句容市| 栖霞市| 团风县| 西乡县| 城固县| 榆中县| 南雄市| 芦山县| 拜泉县| 广东省| 太仓市| 云安县| 蒙山县| 巴中市|