程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ 中不規則窗體的快速顯示

C++ 中不規則窗體的快速顯示

編輯:C++入門知識

  傳統的WINDOWS應用軟件界面給人的感覺總是千篇一律的方方正正的窗體,看的時間長了難免會有些厭煩,總是希望能見到些不同一般的軟件界面。如今,相當數量的商業軟件在提供優秀而強大的功能的同時,軟件的界面也是做得越來越漂亮,比如《超級解霸2000》中的界面插件,使用過的人一定對其華麗的外觀布滿好感。作為一個編程愛好者,假如自己寫出的軟件也擁有類似的界面,也許會吸引更多目光的注視。那麼,我們現在就開始動手制作自己的漂亮界面吧。
  
  技術內幕
  
  要想在自己的程序中加入不規則窗體的應用,你首先要熟悉幾個WINDOWS API函數的使用,它們是:橢圓形(或圓形)區域創建函數CreateEllipticRgn 、多邊形區域創建函數CreatePolygonRgn、 矩形區域創建函數CreateRectRgn、 帶圓角的矩形區域創建函數CreateRoundRectRgn。你可以用這些函數創建不同類型的窗體區域,也可以用WINDOWS API函數CombineRgn將幾個簡單區域組合成一個復雜區域。
  
  下一步要做的就是將已經創建好的區域顯示在屏幕上,同樣也是使用WINDOWS API 函數來實現,這次用到的是SetWindowRgn函數。
  
  WINDOWS API 函數在Borland C++ Builder 頭文件中均已定義,在應用程序中使用這些API函數就象使用C++的普通庫函數一樣。
  
  預備工作:為你的程序預備一幅背景圖片,推薦方法是: 在Photoshop中打開圖片後使用磁性套索工具選取你所需要的圖象輪廓——復制——新建文件(背景使用白色)——粘貼——另存文件(PSD文件)——用ACDSee等看圖軟件將保存的PSD文件轉換為BMP文件face.bmp備用。
  
  程序中引用圖片
  
  打開Borland C++ Builder,在窗體上放置一個Image控件Image1,其Picture暫為空;在窗體上放置一個Popup菜單,編輯菜單項增加“Close”項(添加程序代碼使得激活彈出菜單時即可關閉應用程序)。程序中做如下處理:  
  
  void __fastcall TForm1::FormCreate(TObject *Sender)  
  
  {  
  
  Image1->Picture->LoadFromFile(".face.bmp");  
  
  Width=Image1->Width;
  
  Height=Image1->Height;  
  
  Repaint();  
  
  }
  
  此時,窗體的大小已能跟隨所用圖片的大小而改變,但仍然是傳統的WINDOWS界面,要想顯示成具有圖片輪廓的窗體外形,就需要使用前文介紹的WINDOWS API函數將不需要顯示的部分摳去。  
  
  摳像方法一
  
  這是一種非常簡單的方法,采用對圖片逐行掃描的方式,將圖片像素點為白色的部分摳去,使用的方法是:在像素點四周產生一個包含幾個像素點的矩形,與原圖片采用異或方式摳去,程序如下:
  
  HRGN tepRgn; 
  
  for(y=0;yHeight;y++)  
  
  for(x=0;xWidth;x++)  
  
  if(Image1->Canvas->Pixels[x][y]==clWhite)  
  
  {
  
  < tepRgn=CreateRectRgn(x,y,x+1,y+1);  
  
  CombineRgn(WndRgn,WndRgn,tepRgn,RGN_XOR);  
  
  DeleteObject(tepRgn); 
  
  }
  
  這種方法的優點是處理比較簡單,缺點是處理速度太慢,尤其是在處理大幅圖片時,往往要4~5秒的時間才能將窗體顯示出來。因此產生了通過另外的途徑快速勾勒圖片輪廓的想法。  
  
  摳像方法二
  
  這次我們采用另一個WINDOWS API函數CreatePolygonRgn(多邊形區域),使用這個函數時需為它預備圖片輪廓的坐標點數組及坐標點個數,也是通過對圖片逐行掃描的方式,找到白色像素點與非白色像素點的分界點,將該點的坐標存入數組中,然後用CreatePolygonRgn函數一次就可以把圖片外圍的不用部分摳去,從而省去大量的處理時間。程序如下:  
  
  register int x,y;  
  
  int l,r;
  
  POINT *a; 
  
  bool lb,rb;
  
  HRGN WndRgn,TempRgn,;  
  
  if((a=(POINT *)malloc(800*2*(sizeof(POINT))))==NULL)  
  
  {
  
  ShowMessage("申請內存失敗!");  
  
  exit(0); 
  
  }
  
  l=0;r=Image1->Height*2-1;  
  
  WndRgn=CreateRectRgn(0,0,Image1->Width,Image1->Height);  
  
  for(y=0;yHeight;y++)
  
  {  
  
  lb=true;  
  
  
  for(x=0;xWidth;x++)  
  
  if(Image1->Canvas->Pixels[x][y]!=clWhite)  
  
  {  
  
  a[l].x=x;  
  
  a[l].y=y;  
  
  lb=false;
  
  break;  
  
  }  
  
  if(lb) a[l]=a[l-1];
  
  l++;  
  
  rb=true;
  
  for(x=Image1->Width-1;x>=0;x--)  
  
  if(Image1->Canvas->Pixels[x][y]!=clWhite)  
  
  {  
  
  a[r].x=x;  
  
  a[r].y=y;
  
  rb=false;  
  
  break;  
  
  } 
  
  if(rb) a[r]=a[r+1];  
  
  r--;  
  
  } 
  
  TempRgn=CreatePolygonRgn(a,Image1->Height*2,ALTERNATE);  
  
  CombineRgn(WndRgn,WndRgn,TempRgn,RGN_AND);  
  
  DeleteObject(TempRgn);  
  
  < free(a);
  
  程序中對每一像素行都從左右兩個方向分別掃描,找到兩邊的分界點存入數組。
  
  不過這個方法也存在一些缺陷,那就是圖片的內凹部分輪廓並未表現出來。
  最終解決方案
  
  考慮到既不增加算法的復雜度,又可大幅度縮短不規則窗體的創建速度,因此采用綜合以上兩種方案,達到我們應用的目的,程序中首先應用方法二對圖片雙向掃描,產生輪廓坐標點數組,然後在圖片輪廓內應用方法一將內凹部分摳去,最後才用多邊形區域創建函數摳去圖片外圍部分。程序如下:
  
  void __fastcall TForm1::FormCreate(TObject *Sender)  
  
  {
  
  register int x,y;
  
  int l,r;  
  
  POINT *a;  
  
  bool lb,rb;  
  
  HRGN WndRgn,TempRgn,tepRgn;  
  
  Width=800;Height=600;  
  
  if((a=(POINT *)malloc(800*4*(sizeof(POINT))))==NULL)  
  
  {  
  
  ShowMessage("申請內存失敗!");  
  
  exit(0);  
  
  }
  
  Image1->Picture->LoadFromFile(".face.bmp");  
  
  Width=Image1->Width;  
  
  Height=Image1->Height;  
  
  Repaint();  
  
  l=0;r=Image1->Height*2-1;  
  
  WndRgn=CreateRectRgn(0,0,Image1->Width,Image1->Height);  
  
  < //應用方法二產生輪廓坐標點數組  
  
  for(y=0;yHeight;y++)  
  
  {  
  
  lb=true;
  
  for(x=0;xWidth;x++)  
  
  if(Image1->Canvas->Pixels[x][y]!=clWhite)  
  
  {  
  
  a[l].x=x+1;  
  
  a[l].y=y;  
  
  lb=false;  
  
  break;  
  
  }  
  
  if(lb) a[l]=a[l-1];  
  
  l++;  
  
  rb=true;
  
  for(x=Image1->Width-1;x>=0;x--)  
  
  if(Image1->Canvas->Pixels[x][y]!=clWhite)  
  
  {  
  
  a[r].x=x;  
  
  a[r].y=y;  
  
  rb=false;  
  
  break;  
  
  }  
  
  if(rb) a[r]=a[r+1];  
  
  r--;  
  
  }  
  
  //應用方法一摳去圖片內凹部分  
  
  r=Image1->Height*2-1;  
  
  for(y=0;yHeight;y++){  
  
  for(x=a[y].x;x
  if(Image1->Canvas->Pixels[x][y]==clWhite)  
  
  {  
  
  < tepRgn=CreateRectRgn(x,y,x+1,y+1);  
  
  CombineRgn(WndRgn,WndRgn,tepRgn,RGN_XOR);  
  
  DeleteObject(tepRgn);  
  
  
  }  
  
  r--;  
  
  }   
  
  //將圖片外圍部分摳去  
  
  TempRgn=CreatePolygonRgn(a,Image1->Height*2,ALTERNATE);  
  
  CombineRgn(WndRgn,WndRgn,TempRgn,RGN_AND);  
  
  DeleteObject(TempRgn);  
  
  free(a);  
  
  //顯示不規則窗體  
  
  SetWindowRgn(Handle,WndRgn,true);  
  
  SetWindowPos(Handle,HWND_TOP,0,0,0,0,SWP_NOMOVE SWP_NOSIZE);  
  
  }  
  
  至此,一個漂亮的程序界面就出現在你的屏幕上了。
 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved