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

首頁 > 開發 > 綜合 > 正文

C#截屏問題及FORM間傳值

2024-07-21 02:26:07
字體:
來源:轉載
供稿:網友
國內最大的酷站演示中心!

這個文章還是有一些可以借鑒的地方

-------------------------------------------------------------------------

最近在程序中做一動態截屏功能的小程序;
在完成過程中,遇到了許多問題,
現將其中重要的過程記錄如下:

1,要實現動態截屏的原理
剛開始并不知,以為可以得到桌面的句柄直接調用左右鼠標點擊得到.
哪有那么如想像中的美事
看了許多別人的程序.,特別是qq的動態截屏功能,
他們在截屏的時候桌面都是靜態的.
原來此時的背景是一個最大化的form,把其標題欄,按鈕等都取消了.
像做桌面保護程序那樣的風格.
在這個form中得到它的兩個坐標是很容易的事;
也就是說:先截全屏到一個form中顯示
在這個form中截你所想要的一部分并在第一個form中顯示所截部分;
這樣就出現了要在兩個之間傳值;
最初為了避免傳值(呵呵,當時不會傳值),我先把所截部分保存一張圖片,
在第一個form中檢測是晉中有圖片存在,有則顯示出來
功能是實現了,但有了新問題?只能截一次!
原因是,第二要截屏則要刪除保存的圖片,為第二次截屏準備,但異常顯示
圖片資源被調用,無法刪除.也是為什么第二次截圖不能保存的原因.
mypicturebox.image=null;這樣的操作也不行的.(有誰知道的怎么樣消除調用資源的告訴我一下)
看來這個笨方法不工作了.
在網上找到兩種form間傳值的方法.
一]新建類過渡傳值.
二]傳遞第一個form的地址.

2具體實現
清楚了實現原理,就不難實現其功能了~*~
我先用第二個方法實現!
(1)先在第一個form中用一按鈕啟動截屏程序
            this.hide();//隱藏主對話框.
            thread.sleep(150);//停止一下
           
            allbitmap = getallscreen();//調用動態截屏
           
            capturescreen captures = new capturescreen(allbitmap,this);// 傳遞全屏bitmap和地址
            captures.showdialog();
            this.show();
其中調用了截全屏的函數getallscreen()
        private bitmap getallscreen()
        {
            //建立屏幕graphics
            graphics grpscreen = graphics.fromhwnd(intptr.zero);
            //根據屏幕大小建立位圖
            bitmap bitmap = new bitmap(screen.primaryscreen.bounds.width, screen.primaryscreen.bounds.height, grpscreen);
            //建立位圖相關graphics
            graphics grpbitmap = graphics.fromimage(bitmap);
            //建立屏幕上下文
            intptr hdcscreen = grpscreen.gethdc();
            //建立位圖上下文
            intptr hdcbitmap = grpbitmap.gethdc();
            //將屏幕捕獲保存在圖位中
            bitblt(hdcbitmap, 0, 0, bitmap.width, bitmap.height, hdcscreen, 0, 0, 0x00cc0020);
            //關閉位圖句柄
            grpbitmap.releasehdc(hdcbitmap);
            //關閉屏幕句柄
            grpscreen.releasehdc(hdcscreen);
            //釋放位圖對像
            grpbitmap.dispose();
            //釋放屏幕對像
            grpscreen.dispose();
            //返回捕獲位圖
            return bitmap;
        }
在截全屏函數中用到了一個api函數.
則進行如下操作
using system.runtime.interopservices;

         [dllimportattribute("gdi32.dll")]
         public static extern bool bitblt(
         intptr hdcdest,    //目標設備的句柄
         int nxdest,        // 目標對象的左上角的x坐標
         int nydest,        // 目標對象的左上角的x坐標
         int nwidth,        // 目標對象的矩形的寬度
         int nheight,       // 目標對象的矩形的長度
         intptr hdcsrc,     // 源設備的句柄
         int nxsrc,         // 源對象的左上角的x坐標
         int nysrc,         // 源對象的左上角的x坐標
         system.int32 dwrop // 光柵的操作值
         );

(2)到了最重要的地方,要想把第二個form中的數據傳遞過來就得在第一個form中的相應的顯示處理程序
我用下列函數
        public void setmyimage(bitmap mybitmap)//注意是public類型
        {
            this.mypicturebox.image = mybitmap;//顯示
            myimage = mybitmap;                //用于重畫
            prebtn.enabled = true;             //用于保存圖片
        }
第一個form中用到一些變量
        public image myimage=null;
        public bitmap allbitmap;
(3)在第一個form中調用了第二個form,其中構造函數傳遞了全屏的bitmap,
所以第二個form中加上一個構造函數:
        public capturescreen(bitmap bit,form parentform)
        {
            initializecomponent();
            this.allbitmap = bit;
            this._parentform = parentform;
        }
傳遞了圖片信息在form_load中加載顯示
        private void capturescreen_load(object sender, eventargs e)
        {
            this.topmost = true;//讓其最前顯示
            this.allpicture.image = allbitmap;
      gg = this.allpicture.creategraphics();//創建一個graphics為后面建立提示信息準備
        }
(4)要截部分屏幕,當然要確定一下范圍.用左右鼠標鍵來確定.
用到下面三個函數
        private void allpicture_mousedown(object sender, mouseeventargs e)
        {
            if (isdoubleclick == true)
            {
                point1.x = e.x;
                point1.y = e.y;
                isdraw = true;
                gg.drawstring("按esc鍵退出截圖程序程序", new font("tahoma", 13, fontstyle.underline),
                                  new solidbrush(color.blue), e.x,e.y);
            }
        }

        private void allpicture_mousemove(object sender, mouseeventargs e)
        {
            this.allpicture.refresh();
            if (isdraw == true)
            {
                int hh,ww;         //計算截圖位置和開始點位置
                point startpoint=new point(0,0);
                if (e.x < point1.x && e.y < point1.y)
                {
                    startpoint.x = e.x;
                    startpoint.y = e.y;
                    hh = (int)(point1.x - e.x);
                    ww = (int)(point1.y - e.y);
                }
                if (e.x > point1.x && e.y < point1.y)
                {
                    startpoint.x = point1.x;
                    startpoint.y = e.y;
                    hh = (int)(e.x - point1.x);
                    ww = (int)(point1.y - e.y);
                }
                if (e.x < point1.x && e.y > point1.y)
                {
                    startpoint.x = e.x;
                    startpoint.y = point1.y;
                    hh = (int)(point1.x - e.x);
                    ww = (int)(e.y - point1.y);
                }
                else
                {
                    startpoint = point1;
                    hh = (int)(e.x - point1.x);
                    ww = (int)(e.y - point1.y);
                }
                gg.drawrectangle(new pen(color.fromargb(9, 247, 32)), startpoint.x,
                                            startpoint.y, hh, ww);//截圖范圍示意圖
               
                int hhh, www;//顯示提示信息位置
                if ((int)(e.x - point1.x) > 0)
                    hhh = (int)(e.x - point1.x);
                else
                    hhh = (int)(point1.x - e.x);
                if ((int)(e.y - point1.y) > 0)
                    www = (int)(e.y - point1.y);
                else
                    www = (int)(point1.y - e.y);
                string mystr = "截取范圍:/n    寬:" + hhh + "/n    高:" + www;
                gg.drawstring(mystr, new font("tahoma", 10, fontstyle.underline),
                                     new solidbrush(color.red), e.x,e.y);//h1, w1);
                gg.drawstring("按esc鍵退出截圖程序程序", new font("tahoma", 13, fontstyle.underline),
                                                         new solidbrush(color.blue), point1.x, point1.y-22);         
            }
        }

        private void allpicture_mouseup(object sender, mouseeventargs e)
        {
            if (isdoubleclick == true)
            {
                point2.x = e.x;
                point2.y = e.y;
                isdoubleclick = false;
            }
        }

第二個form中用到的變量:
        private point  point1 = new point();   //開始位置
        private point  point2 = new point();   //最后位置
        private bool   isdraw = false;         //是否開始畫直線
        private bool   isdoubleclick = true;    //是否可以雙擊
        public  bitmap newbitmap;               //截的部分圖像
        private bitmap allbitmap;              //全屏圖像
        private form   _parentform = null;
        private graphics gg;

        public static int h1;//顯示提示位置
        public static int w1;
截屏用到的api函數:
        #region 導入函數
       
        [dllimport("gdi32.dll")]
        private static extern intptr createdc(string lpszdriver, string lpszdrivse, string lpszoutput, int32 lpinitdata);

        [dllimport("gdi32.dll")]
        private static extern intptr createcompatibledc(intptr hdc);

        [dllimport("gdi32.dll")]
        private static extern int getdevicecaps(intptr hdc, int32 nindex);

        [dllimport("gdi32.dll")]
        private static extern intptr createcompatiblebitmap(intptr hdc, int nwidth, int nheight);

        [dllimport("gdi32.dll")]
        private static extern intptr selectobject(intptr hdc, intptr hgdiobj);

        [dllimport("gdi32.dll")]
        private static extern int bitblt(intptr hdcdest, int nxdest, int nydest,
                 int nwidth, int nheight, intptr hdcsrc, int nxsrc, int nysrc, uint32 dwrop);

        [dllimport("gdi32.dll")]
        private static extern int deletedc(intptr hdc);

        #endregion
(5)現在可以調用截取部分屏幕的函數  
        private void allpicture_doubleclick(object sender, eventargs e)
        {
            this.allpicture.refresh();//先擦出提示信息,食品店提示信息什么地方都可以顯示;
            newbitmap = getpartscreen(point1, point2);
            ((mytool)_parentform).setmyimage(newbitmap);//通過傳地址調用第一個form的圖片顯示函數
            this.close();//該窗口關閉 // application.exit();應用程序退出
        }
下面是getpartscreen函數的具體實現 private static bitmap getpartscreen(point p, point pp)
        {
            intptr hscrdc, hmemdc;
            intptr hbitmap, holdbitmap;
            int nx, ny, nxx, nyy;
            nx = nxx = ny = nyy = 0;
            int nwidth, nheight;
            int xscrn, yscrn;

            hscrdc = createdc("display", null, null, 0);//(intptr)null);// 0);//創建dc句柄
            hmemdc = createcompatibledc(hscrdc);//創建一個內存dc
            xscrn = getdevicecaps(hscrdc, 8);//*horzres*/);//獲取屏幕寬度//wingdi.h
            yscrn = getdevicecaps(hscrdc, 10);//*vertres*/);//獲取屏幕高度//wingdi.h

            nx = p.x;
            ny = p.y;
            nxx = pp.x;
            nyy = pp.y;    

            if (nx < 0)      //檢查數值合法性
                nx = 0;
            if (ny < 0)
                ny = 0;
            if (nxx > xscrn)
                nxx = xscrn;
            if (nyy > yscrn)
                nyy = yscrn;

            if (nxx - nx > 0)//截取范圍的寬度
            {
                nwidth = nxx - nx;
            }
            else
            {
                nwidth = nx - nxx;
            }
            if (nyy - ny > 0)//截取范圍的高度
            {
                nheight = nyy - ny;
            }
            else
            {
                nheight = ny - nyy;
            }

            if (nxx < nx && nyy < ny)
            {
                h1 = nx;
                w1 = ny;

                int k;
                k = nxx;
                nxx = nx;
                nx = k;

                k = nyy;
                nyy = ny;
                ny = k;
            }

            if (nxx < nx && nyy > ny)
            {
                h1 = nx;
                w1 = nyy;

                nx = nxx;
            }
            if (nx < nxx && ny > nyy)
            {
                h1=nx;
                w1 = nyy;

                ny = nyy;
            }

            hbitmap = createcompatiblebitmap(hscrdc, nwidth, nheight);//從內存dc復制到hbitmap句柄
            holdbitmap = selectobject(hmemdc, hbitmap);
            bitblt(hmemdc, 0, 0, nwidth, nheight, hscrdc, nx, ny, (uint32)0xcc0020);
            hbitmap = selectobject(hmemdc, holdbitmap);
            deletedc(hscrdc);//刪除用過的對象
            deletedc(hmemdc);//刪除用過的對象
            return bitmap.fromhbitmap(hbitmap);//用bitmap.fromhbitmap從hbitmap返回bitmap
        }
(6)我們傳遞了地址.怎么實現的傳地址呢.委托!(具體委托知識請查教程委托部分!)
在第一個form中申請委托:
public delegate void mydelegate(bitmap mybitmap);//類外

全部功能實現,可你會發現傳遞的圖片沒有顯示在第一個form中的圖片控件中
為什么呢,我可是花了七八個小時才知,因為那時我暈了
原來我們在截圖時隱藏了form1,又接著顯示,再關閉了form2,使顯示的圖片沒有更新,
所以現在你知道該怎么做了吧.
重載onpaint函數:
        protected override void onpaint(painteventargs e)
        {
            base.onpaint(e);
            if (myimage != null)
                this.mypicturebox.image = myimage;
            else
            {
                this.mypicturebox.image = null;
                this.mypicturebox.refresh();
            }
        }
(7)大功告成,不知你是否!
(8)現在簡單用過渡類實現一下傳值:
我只給出不相同的部分,有不明白的可以聯系我共同討論;
第一個form截屏時
            passbitmap newpassbitmap = new passbitmap();//注意這.
            newpassbitmap.passbitmapevent += new sendbitmap(this.setmyimage);
           
            this.hide();
            thread.sleep(150);
           
            allbitmap = getallscreen();//調用動態截屏
           
            capturescreen captures = new capturescreen(allbitmap, newpassbitmap);
            captures.showdialog();
            this.show();
第二個form的構造函數
        public capturescreen(bitmap bit,passbitmap bitmapss)
        {
            initializecomponent();
            this.allbitmap = bit;
            this.bitmapss=bitmapss;
        }
雙擊截屏時:
            newbitmap = getpartscreen(point1, point2);
            bitmapss.passgetbitmap(newbitmap);

其中過渡類:
using system;
using system.drawing;

namespace bobertool
{
    public delegate void sendbitmap(bitmap mybitmap);

    public class passbitmap
    {
        public bitmap mybitmaps;
        public event sendbitmap passbitmapevent;

        public void passgetbitmap(bitmap bitmaps)
        {
            if (bitmaps != null)
                passbitmapevent(bitmaps);
        }
    }
}

基本上實現了功能!
由于我是初學者.其中必然存在許多小問題,歡迎大家和我共同討論!
qq47145481
e-mail:[email protected]

2006.10.28


 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 巴中市| 林周县| 炎陵县| 七台河市| 长兴县| 马公市| 凤山市| 集贤县| 闽清县| 无极县| 定州市| 进贤县| 武川县| 新乐市| 蕉岭县| 宽甸| 望江县| 肃南| 陇西县| 大化| 鄂尔多斯市| 治多县| 临泽县| 哈密市| 金沙县| 瓮安县| 花垣县| 阿拉善右旗| 青浦区| 乌恰县| 乐安县| 绥化市| 西藏| 冀州市| 沙洋县| 阳朔县| 仁化县| 麻城市| 任丘市| 巢湖市| 呼伦贝尔市|