如题

解决方案 »

  1.   

    Copy and paste---- 在Windows 系 统 中 窗 口 的 默 认 形 状 是 矩 形, 在 实 际 应 用 中 绝 大 多 数 窗 口 都 是 标 准 矩 形 窗 口。 如 果 一 个 窗 口 有 着 与 众 不 同 的 形 状, 则 会 非 常 引 人 注 目, 如 何 创 建 非 标 准 窗 口 呢? 
    ----在Windows, 可 以 通 过 调 用SetWindowRgn ( 在MFC 类 库 中 对 应 的 函 数 为CWnd::SetWindowRgn) 来 设 置 窗 口 的 形 状, 函 数 的 定 义 如 下: 
    ---- int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedrawflag); 
    ----窗 口 的 形 状 由 参 数 hRgn 所 标 志 的 的 区 域 (region) 决 定。 通 过 创 建 不 同 的 区 域 就 可 以 创 建 不 同 形 状 的 窗 口。 下 面 的 代 码, 可 以 产 生 圆 角 矩 形 的 窗 口。 
    CRgn trgn ;
    trgn.CreateRoundRectRgn( 0 , 0 , 200 , 200 , 30 , 30 ) ;
    SetWindowRgn( trgn , TRUE ) ;
    ----效 果 如 下 图 所 示: 
    ----Windows 还 支 持 由 路 径( Path ) 创 建 区 域 ( Region ), 通 过 这 个 途 径 我 们 还 可 以 创 建 文 字 形 状 的 窗 口。 
    ----下 面 的 代 码 可 以 创 建 形 状 为“ 计 算 机 世 界" 五 个 字 的 窗 口。 
     +CDC * pDC = GetDC() ;
    CFont rfont , *pOldFont ;
    CRgn m_rgn ;
    rfont.CreatePointFont( 1000 , “ 隶 书" ) ;
    pOldFont = pDC ->SelectObject( &rfont ) ;
    pDC ->BeginPath() ;
    pDC ->SetBkMode( TRANSPARENT ) ;
    CString stxt = “ 计 算 机 世 界" ;
    pDC ->TextOut( 0 , 0 , stxt ) ;
    pDC ->EndPath() ;
    m_rgn.CreateFromPath( pDC ) ;pDC ->SelectObject( pOldFont ) ;
    ReleaseDC( pDC ) ;
          SetWindowRgn( m_rgn , TRUE ) ;
    ----效 果 如 下 图 所 示: 
    ----那 么 我 们 能 不 能 创 建 任 意 形 状 的 窗 口 呢? 也 就 是 创 建 任 意 形 状 的 区 域 呢? 答 案 是 肯 定 的。 大 家 请 看 下 面 这 个 圆 号 形 状 的 窗 口。 
    ----创 建 这 样 的 一 个 区 域 是 调 用 SDK 的 ExtCreateRegion 来 实 现( MFC 中 的 对 应 函 数 为CRgn::CreateFromData)。 这 个 函 数 是 通 过 提 供 一 个 矩 形 数 组, 来 创 建 一 个 由 这 些 矩 形 组 成 的 区 域。 而 创 建 圆 号 区 域 的 过 程 就 是 由 一 个 圆 号 的 位 图 生 成 矩 形 数 组, 再 由 这 个 矩 形 数 组 生 成 区 域 的 过 程。 
    ----下 面 是 由 圆 号 位 图 创 建 区 域 的 函 数 代 码。 
    CDib m_dib ;
    CRgn m_rgn ;
    COLORREF m_dwColorKey = 0x0000ff; // 透 明 色, 纯 蓝
    BOOL CAswDlg::CreateRegionFromBmp( LPCSTR lpsFName )
    {
    // 读 入 位 图  
    if( !m_dib.Open( lpsFName ) )
         return FALSE ;
    SIZE dibsize ;
    // 获 取 位 图 尺 寸
    dibsize = m_dib.GetSize( ) ;
    int i , j ;
    BOOL bkey ;
    int iCount = 0 ;
    // 统 计 需 要 的 矩 形 个 数
    for( i = 0 ; i < dibsize.cy ; i + + )
    {
        bkey = TRUE ;
        for( j = 0 ; j < dibsize.cx ; j + + )
        {
        if( m_dib.GetPixel( j , i ) == m_dwColorKey )
             {
                   bkey = TRUE ;
             }
             else
             {
                   if( bkey )
                   {
                       iCount + + ;
                   }
                   bkey = FALSE ;
             }
        }
    }
    BYTE *pData ;
    RGNDATA *pRgnData ;
    RECT *pRect ;
    int iIndex = 0 ;pData = new BYTE[ sizeof
     ( RGNDATAHEADER ) + sizeof( RECT ) * iCount ] ; 
    pRgnData = ( RGNDATA * )pData ;
    pRect = ( RECT * )( pData + sizeof( RGNDATAHEADER ) ) ;
    pRgnData ->rdh.dwSize =sizeo(RGNDATAHEADER ) ;
    pRgnData ->rdh.iType      =RDH_RECTANGLES ;
    pRgnData ->rdh.nCount    = iCount ;
    pRgnData ->rdh.nRgnSize  = sizeof( RECT ) *iCount ;
    pRgnData ->rdh.rcBound.left          = 0 ;
    pRgnData ->rdh.rcBound.top         = 0 ;
    pRgnData ->rdh.rcBound.right        =dibsize.cx ;
    pRgnData ->rdh.rcBound.bottom  = dibsize.cy ;
    int iLeft = 0 ;
    for( i = dibsize.cy - 1 ; i >= 0  ; i - - ) 
    // 因 为Bitmap 位 图 在Y 方 向 是 颠 倒 
      的 所 以 要 从 底 部 开 始
    {
            bkey = TRUE ;
            iLeft = -1 ;
            for( j = 0 ; j < dibsize.cx ; j + + )
            {
            if( m_dib.GetPixel( j , i ) == m_dwColorKey )
            {
                if( !bkey )
                {
                pRect[ iIndex ].left = iLeft ;
                pRect[ iIndex ].right = j ;
                pRect[ iIndex ].top = dibsize.cy - i - 1 ;
                pRect[iIndex].bottom = dibsize.cy -i;
                bkey = TRUE ;
                iIndex + + ;
                iLeft = -1 ;
                }
            }
                  else
                  {
                       if( bkey )
                       {
                           iLeft = j ; 
                           bkey = FALSE ;
                       }
                  }
            }
         if( iLeft >= 0 )
            {
                pRect[ iIndex ].left = iLeft ;
                pRect[ iIndex ].right = dibsize.cx ;
                pRect[ iIndex ].top = i ;
                pRect[ iIndex ].bottom = i ;
                iIndex + + ;
            }
     }
          BOOL br = m_rgn.CreateFromData
    ( NULL , sizeof( RGNDATAHEADER ) +sizeof
     ( RECT ) * iCount , pRgnData ) ;
          return br ; 
    }
    ----有 了 这 个 方 法, 任 意 形 状 的 窗 口 都 可 以 被 创 建, 只 要 先 画 出 想 要 的 形 状 位 图 即 可。 
    ----这 里 还 要 谈 到 一 个 问 题, 任 意 形 状 的 窗 口 没 有 标 题 栏, 那 么 用 户 如 何 拖 动 窗 口 呢? 其 实 只 要 在 响 应 左 键 点 击 消 息 时 调 用SendMessage( WM_SYSCOMMAND , SC_MOVE | HTCLIENT , 0 ) 即 可。 
      

  2.   

    给你参考一下字体窗体
    procedure TForm1.FormCreate(Sender: TObject);
    var rgn:HRGN;
    begin
    Form1.Color:=clRed;
    BeginPath(Canvas.Handle);
    SetBKMode(Canvas.Handle,TRANSPARENT);
    Canvas.Font.Name:='宋体';
    Canvas.Font.Size:=200;
    Canvas.TextOut(150,130,'程序员');
    EndPath(Canvas.Handle);
    rgn:=PathToRegion(Canvas.Handle);
    SetWindowRgn(Handle,rgn,true);
    end;