c#打印預(yù)覽控件中實(shí)現(xiàn)用鼠標(biāo)移動(dòng)頁(yè)面功能代碼分享
該功能本來(lái)可以通過(guò)拉動(dòng)水平和垂直滾動(dòng)條來(lái)實(shí)現(xiàn),但實(shí)際使用中,用戶更趨向于直接用鼠標(biāo)拖動(dòng)頁(yè)面來(lái)實(shí)現(xiàn),很多看圖類軟件都有這種類似的功能。而.net的打印預(yù)覽控件卻很遺憾的沒(méi)有提供這一功能,只來(lái)自己想辦法來(lái)實(shí)現(xiàn)啦。
我的辦法就是用代碼來(lái)控制打印預(yù)覽控件中的水平來(lái)垂直滾動(dòng)條的位置,間接實(shí)現(xiàn)和用鼠標(biāo)直接拖動(dòng)滾動(dòng)條一樣的效果。
在實(shí)現(xiàn)這一功能的過(guò)程中,最大的困難是打印預(yù)覽控件并沒(méi)有讓程序員直接調(diào)用的關(guān)于滾動(dòng)條的方法或?qū)傩?。所以只好向WinAPI求助了。
以下API函數(shù)和常量就是實(shí)現(xiàn)上述功能的關(guān)鍵了:
[DllImport("user32.dll")]
private static extern int SetScrollPos(IntPtr hwnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
private static extern int GetScrollPos(IntPtr hwnd, int nBar);
[DllImport("user32.dll")]
private static extern bool PostMessage(IntPtr hWnd, int nBar, int wParam, int lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);
private const int SB_HORZ = 0x0;
private const int SB_VERT = 0x1;
private const int WM_HSCROLL = 0x114;
private const int WM_VSCROLL = 0x115;
private const int SB_THUMBPOSITION = 4;
簡(jiǎn)單說(shuō)明一下吧:
SetScrollPos:設(shè)置所指定滾動(dòng)條中的滾動(dòng)按鈕的位置
GetScrollPos:獲取指定滾動(dòng)條的滾動(dòng)按鈕的位置
GetScrollRange:獲取指定滾動(dòng)條的滾動(dòng)按鈕的位置最大最小值
PostMessage:這個(gè)函數(shù)是關(guān)鍵中的關(guān)鍵,它負(fù)責(zé)向Windows控件發(fā)送相應(yīng)的消息,以真正執(zhí)行相應(yīng)的操作。一些網(wǎng)友實(shí)現(xiàn)了滾動(dòng)條中滑塊位置的移動(dòng),但卻沒(méi)有引起控件中內(nèi)容的移動(dòng),其原因就是因?yàn)闆](méi)有調(diào)用這個(gè)函數(shù),沒(méi)有把移動(dòng)內(nèi)容的消息發(fā)送給控件。
SB_HORZ :代表水平滾動(dòng)條
SB_VERT :代表垂直滾動(dòng)條
WM_HSCROLL :代表水平滾動(dòng)事件
WM_VSCROLL :代表垂直滾動(dòng)事件
SB_THUMBPOSITION :至于這個(gè)常量,其含義我也不是很清楚,有知道的朋友歡迎回復(fù)給我。
好了,準(zhǔn)備工作做好了,就可以開工了。
先聲明幾個(gè)變量:
bool Preview_move = false;//是否按下鼠標(biāo),表示處理移動(dòng)狀態(tài)。
Point MoveStart;//移動(dòng)開始時(shí),鼠標(biāo)的坐標(biāo)點(diǎn)
Point MoveEnd;//移動(dòng)過(guò)程中鼠標(biāo)的坐標(biāo)點(diǎn)
在控件的MouseDown事件中,當(dāng)鼠標(biāo)按下時(shí)開始移動(dòng)頁(yè)面,并記下起始坐標(biāo)點(diǎn):
private void previewer_MouseDown(object sender, MouseEventArgs e)
{
Preview_move = true;
MoveStart = e.Location;
}
在控件的MouseUp事件中,記得當(dāng)鼠標(biāo)放開后要置回非移動(dòng)狀態(tài):
private void previewer_MouseUp(object sender, MouseEventArgs e)
{
Preview_move = false;
以下就是實(shí)現(xiàn)移動(dòng)頁(yè)面的關(guān)鍵部分了,在控件的MouseMove實(shí)現(xiàn)用代碼間接控制控件的滾動(dòng)條位置并實(shí)現(xiàn)頁(yè)面實(shí)時(shí)移動(dòng):
private void previewer_MouseMove(object sender, MouseEventArgs e)
{
if (!Preview_move) return;
MoveEnd = e.Location;
int MinH,MaxH,MinV,MaxV;
//獲得鼠標(biāo)在X和Y兩個(gè)方向上的移動(dòng)量。除以10是為是讓移動(dòng)頁(yè)面的速度變慢一點(diǎn)。而前面的負(fù)號(hào)則是用來(lái)調(diào)節(jié)頁(yè)面移動(dòng)方向的。
int MoveX = -(MoveEnd.X - MoveStart.X)/10;
int MoveY = -(MoveEnd.Y - MoveStart.Y)/10;
//獲取滾動(dòng)條的最大最小位置和當(dāng)前位置
GetScrollRange(previewer.Handle, 0, out MinH, out MaxH);
GetScrollRange(previewer.Handle, 1, out MinV, out MaxV);
int PosH = GetScrollPos(previewer.Handle, 0);
int PosV = GetScrollPos(previewer.Handle, 1);
//計(jì)算最終滾動(dòng)條的位置(注意最終位置不要超出最大最小值的范圍)
int PosH1 = PosH + MoveX;
if (PosH1 >= MinH && PosH1 <= MaxH)
{
SetScrollPos(previewer.Handle, SB_HORZ, PosH1, true);//設(shè)置滾動(dòng)條的位置
PostMessage(previewer.Handle, WM_HSCROLL, SB_THUMBPOSITION + 0x10000 * PosH1, 0);//告訴控件移動(dòng)頁(yè)面內(nèi)容到相應(yīng)的位置上
}
int PosV1 = PosV + MoveY;
if (PosV1 >= MinV && PosV1 <= MaxV)
{
SetScrollPos(previewer.Handle, SB_VERT, PosV1, true);
PostMessage(previewer.Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * PosV1, 0);
}
}
OK,一個(gè)能用鼠標(biāo)實(shí)時(shí)移動(dòng)頁(yè)面內(nèi)容的打印預(yù)覽功能作好了。其實(shí),對(duì)于.net中很多控件都可以用相似的方面實(shí)現(xiàn)對(duì)滾動(dòng)條的控制
相關(guān)文章
使用位運(yùn)算實(shí)現(xiàn)網(wǎng)頁(yè)中的過(guò)濾、篩選功能實(shí)例
這篇文章主要介紹了使用位運(yùn)算實(shí)現(xiàn)網(wǎng)頁(yè)中的過(guò)濾、篩選功能實(shí)例,一個(gè)比常規(guī)拼接SQL字符串更有新意的一個(gè)解決思路,需要的朋友可以參考下2014-07-07
C#不重復(fù)輸出一個(gè)數(shù)組中所有元素的方法
這篇文章主要介紹了C#不重復(fù)輸出一個(gè)數(shù)組中所有元素的方法,涉及C#針對(duì)數(shù)組的遍歷、校驗(yàn)及排序等操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
C#自定義實(shí)現(xiàn)多程序共享內(nèi)存空間
這篇文章主要為大家詳細(xì)介紹了C#如何自定義實(shí)現(xiàn)多程序共享內(nèi)存空間,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-10-10
c#中SAPI使用總結(jié)——SpVoice的使用方法
最近使用C#重做了點(diǎn)名系統(tǒng)(要用到TTS,讓計(jì)算機(jī)點(diǎn)名)使用了SAPI,在這里總結(jié)一下SpVoice的使用方法。2011-10-10
C# 漢字轉(zhuǎn)拼音(全拼和首字母)實(shí)例
這篇文章介紹了C# 漢字轉(zhuǎn)拼音(全拼和首字母)實(shí)例代碼,有需要的朋友可以參考一下2013-10-10
WinForm實(shí)現(xiàn)狀態(tài)欄跑馬燈效果的方法示例
這篇文章主要介紹了WinForm實(shí)現(xiàn)狀態(tài)欄跑馬燈效果的方法,涉及WinForm控件結(jié)合時(shí)間函數(shù)動(dòng)態(tài)操作元素屬性的相關(guān)技巧,需要的朋友可以參考下2017-07-07
C#中GraphicsPath的Widen方法用法實(shí)例
這篇文章主要介紹了C#中GraphicsPath的Widen方法用法,實(shí)例分析了Widen方法的使用技巧,需要的朋友可以參考下2015-06-06

