Click here to Skip to main content
15,888,221 members
Articles / Desktop Programming / MFC

Replace a Window's Internal Scrollbar with a customdraw scrollbar Control

Rate me:
Please Sign up or sign in to vote.
4.47/5 (60 votes)
17 Jun 2007CPOL3 min read 561.2K   9.7K   130   106
Shows how to replace a window's scrollbar with a skinable scrollbarctrl
Sample Image - skinscrollbar_demo.gif

Introduction

This is my first article. At first, I must express my thanks to CodeProject and all the selfless people.

I have tried to look for a sample to show me how to skin a window's internal scrollbar, but, unfortunately, I failed. Some days ago, I got inspiration: In order to skin a window's internal scrollbar, it may be possible to hide a window's scrollbar below a frame window whose size is smaller than the window, but is the window's parent.

I gave it a try and I succeeded!

Two Main Components

In my code, you will find two main components:

  1. CSkinScrollBar (derived from CScrollBar)
  2. CSkinScrollWnd (derived from CWnd)

CSkinScrollBar offers an owner draw scrollbar. What I have done is handle mouse input and paint message simply, and I do not intend to describe it in detail. If you are interested in it, you can look into my code.

CSkinScrollWnd is the Code's Core

C++
BOOL CSkinScrollWnd::SkinWindow(CWnd *pWnd,HBITMAP hBmpScroll)
{//create a frame windows set
 ASSERT(m_hWnd==NULL);
 m_hBmpScroll=hBmpScroll;

//calc scrollbar wid/hei according to the input bitmap handle
 BITMAP bm;
 GetObject(hBmpScroll,sizeof(bm),&bm);
 m_nScrollWid=bm.bmWidth/9;

 CWnd *pParent=pWnd->GetParent();
 ASSERT(pParent);
 RECT rcFrm,rcWnd;
 pWnd->GetWindowRect(&rcFrm);
 pParent->ScreenToClient(&rcFrm);
 rcWnd=rcFrm;
 OffsetRect(&rcWnd,-rcWnd.left,-rcWnd.top);
 UINT uID=pWnd->GetDlgCtrlID();

//remove original window's border style and add it to frame window
 DWORD dwStyle=pWnd->GetStyle();
 DWORD dwFrmStyle=WS_CHILD|SS_NOTIFY;
 DWORD dwFrmStyleEx=0;
 if(dwStyle&WS_VISIBLE) dwFrmStyle|=WS_VISIBLE;
 if(dwStyle&WS_BORDER)
 {
  dwFrmStyle|=WS_BORDER;
  pWnd->ModifyStyle(WS_BORDER,0);
  int nBorder=::GetSystemMetrics(SM_CXBORDER);
  rcWnd.right-=nBorder*2;
  rcWnd.bottom-=nBorder*2;
 }
 DWORD dwExStyle=pWnd->GetExStyle();
 if(dwExStyle&WS_EX_CLIENTEDGE)
 {
  pWnd->ModifyStyleEx(WS_EX_CLIENTEDGE,0);
  int nBorder=::GetSystemMetrics(SM_CXEDGE);
  rcWnd.right-=nBorder*2;
  rcWnd.bottom-=nBorder*2;
  dwFrmStyleEx|=WS_EX_CLIENTEDGE;
 }

//create frame window at original window's rectangle and 
//set its ID equal to original window's ID.
 this->CreateEx(dwFrmStyleEx,AfxRegisterWndClass(NULL),
	"SkinScrollBarFrame",dwFrmStyle,rcFrm,pParent,uID);

//create a limit window. it will clip target window's scrollbar. 
m_wndLimit.Create(NULL,"LIMIT",WS_CHILD|WS_VISIBLE,CRect(0,0,0,0),this,200);

//create my scrollbar ctrl
 m_sbHorz.Create(WS_CHILD,CRect(0,0,0,0),this,100);
 m_sbVert.Create(WS_CHILD|SBS_VERT,CRect(0,0,0,0),this,101);
 m_sbHorz.SetBitmap(m_hBmpScroll);
 m_sbVert.SetBitmap(m_hBmpScroll);

//change target's parent to limit window
 pWnd->SetParent(&m_wndLimit);

//attach CSkinScrollWnd data to target window's userdata. 

//Remark: use this code, obviously, you will never try to use userdata!!
 SetWindowLong(pWnd->m_hWnd,GWL_USERDATA,(LONG)this);

//subclass target window's wndproc
 m_funOldProc=(WNDPROC)SetWindowLong(pWnd->m_hWnd,GWL_WNDPROC,(LONG)HookWndProc);

 pWnd->MoveWindow(&rcWnd);

//set a timer. it will update scrollbar's information at times.

//I have tried to hook some messages so as to update scrollinfo timely.
//For example, WM_ERESEBKGND and WM_PAINT. 
//But with spy++'s aid, I found if the window's client area need not update,
// my hook proc would hook nothing except some control-depending interfaces. 
 SetTimer(TIMER_UPDATE,500,NULL);
 return TRUE;
}
static LRESULT CALLBACK
HookWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{//my hook function
 CSkinScrollWnd *pSkin=(CSkinScrollWnd*)GetWindowLong(hwnd,GWL_USERDATA);
 LRESULT lr=::CallWindowProc(pSkin->m_funOldProc,hwnd,msg,wp,lp);
 if(pSkin->m_bOp) return lr;
 if(msg==WM_ERASEBKGND)
 {//update scroll info
   SCROLLINFO si;
   DWORD dwStyle=::GetWindowLong(hwnd,GWL_STYLE);
   if(dwStyle&WS_VSCROLL)
   {
    memset(&si,0,sizeof(si));
    si.cbSize=sizeof(si);
    si.fMask=SIF_ALL;
    ::GetScrollInfo(hwnd,SB_VERT,&si);
    pSkin->m_sbVert.SetScrollInfo(&si);
    pSkin->m_sbVert.EnableWindow(si.nMax>=si.nPage);
   }
   if(dwStyle&WS_HSCROLL)
   {
    memset(&si,0,sizeof(si));
    si.cbSize=sizeof(si);
    si.fMask=SIF_ALL;
    ::GetScrollInfo(hwnd,SB_HORZ,&si);
    pSkin->m_sbHorz.SetScrollInfo(&si);
    pSkin->m_sbHorz.EnableWindow(si.nMax>=si.nPage);
   }
 }else if(msg==WM_NCCALCSIZE && wp)
 {//recalculate scroll bar display area.
   LPNCCALCSIZE_PARAMS pNcCalcSizeParam=(LPNCCALCSIZE_PARAMS)lp;
   DWORD dwStyle=::GetWindowLong(hwnd,GWL_STYLE);
   DWORD dwExStyle=::GetWindowLong(hwnd,GWL_EXSTYLE);
   BOOL  bLeftScroll=dwExStyle&WS_EX_LEFTSCROLLBAR;
   int nWid=::GetSystemMetrics(SM_CXVSCROLL);
   if(dwStyle&WS_VSCROLL) 
   {
    if(bLeftScroll)
     pNcCalcSizeParam->rgrc[0].left-=nWid-pSkin->m_nScrollWid;
    else
     pNcCalcSizeParam->rgrc[0].right+=nWid-pSkin->m_nScrollWid;
   }
   if(dwStyle&WS_HSCROLL) pNcCalcSizeParam->rgrc[0].bottom+=nWid-pSkin->m_nScrollWid;
   
   RECT rc,rcVert,rcHorz;
   ::GetWindowRect(hwnd,&rc);
   ::OffsetRect(&rc,-rc.left,-rc.top);
   
   nWid=pSkin->m_nScrollWid;
   if(bLeftScroll)
   {
    int nLeft=pNcCalcSizeParam->rgrc[0].left;
    int nBottom=pNcCalcSizeParam->rgrc[0].bottom;
    rcVert.right=nLeft;
    rcVert.left=nLeft-nWid;
    rcVert.top=0;
    rcVert.bottom=nBottom;
    rcHorz.left=nLeft;
    rcHorz.right=pNcCalcSizeParam->rgrc[0].right;
    rcHorz.top=nBottom;
    rcHorz.bottom=nBottom+nWid;
   }else
   {
    int nRight=pNcCalcSizeParam->rgrc[0].right;
    int nBottom=pNcCalcSizeParam->rgrc[0].bottom;
    rcVert.left=nRight;
    rcVert.right=nRight+nWid;
    rcVert.top=0;
    rcVert.bottom=nBottom;
    rcHorz.left=0;
    rcHorz.right=nRight;
    rcHorz.top=nBottom;
    rcHorz.bottom=nBottom+nWid;
   }
   if(dwStyle&WS_VSCROLL && dwStyle&WS_HSCROLL)
   {
    pSkin->m_nAngleType=bLeftScroll?1:2;
   }else
   {
    pSkin->m_nAngleType=0;
   }
   if(dwStyle&WS_VSCROLL)
   {
    pSkin->m_sbVert.MoveWindow(&rcVert);
    pSkin->m_sbVert.ShowWindow(SW_SHOW);
   }else
   {
    pSkin->m_sbVert.ShowWindow(SW_HIDE);
   }
   if(dwStyle&WS_HSCROLL)
   {
    pSkin->m_sbHorz.MoveWindow(&rcHorz);
    pSkin->m_sbHorz.ShowWindow(SW_SHOW);
   }else
   {
    pSkin->m_sbHorz.ShowWindow(SW_HIDE);
   }
   pSkin->PostMessage(UM_DESTMOVE,dwStyle&WS_VSCROLL,bLeftScroll);
 }
 return lr;
}

//the only global function
//param[in] CWnd *pWnd: target window
//param[in] HBITMAP hBmpScroll: bitmap handle used by scrollbar control.
//return CSkinScrollWnd*:the frame pointer

CSkinScrollWnd* SkinWndScroll(CWnd *pWnd,HBITMAP hBmpScroll);

With the help of my code, you just need to add a line of code in your code. For example, assume you have a treectrl in a window and you want to replace it's scrollbar. At first, you give it a name m_ctrlTree. The next step is when it gets initialized, add a line like this:

C++
SkinWndScroll(&m_ctrlTree,hBmpScroll)

How To Test My Project?

There are 4 types of controls in the interface, including listbox, treectrl, editctrl, richeditctrl respectively. Clicking list_addstring button will fill listctrl and you will see a left scrollbar. Clicking tree_addnode button will fill treectrl and you may see two ownerdraw scrollbars replace its internal scrollbar. Input text in two editboxes to see whether it works.

How To Prepare Your Scrollbar Bitmap?

Both vertical and horizontal scrollbars require 4 image segments. They are arrow-up/arrow-left, slide, thumb and arrow-down/arrow-right. Each of them includes 3 states: normal, hover, press. (It is possible to extend support for state easily. Because I'm not good at image processing, the sample bitmap came from a software's resource.) Beside those segments, the bitmap includes two angle segments located at bitmap's right.

Sample image

Now I Want to Show You the Problems I Have Encountered

  1. When I began this code, I tried to use a scrollbarctrl to cover the window's internal scrollbar. In my mind, only if my scrollbar window's Z order is higher, it will work well. But in fact, it does not work. Although my scrollbar window's z-order is higher, when mouse moves to scrollbar area, the internal scrollbar will render immediately. I have to add a new window as a frame to the target window.
  2. At first, I did not intend to support leftscrollbar style, and my code worked well. Finally, I decided to support it. But what makes me depressed is that it does not work any more. After spending a lot of time on debugging, I found it's wrong to move the window in the subclass callback function. So I defined a user message, and posted the message to the message queue.

How To Apply It to a ListCtrl?

Thanks to kangcorn for finding the problem.

When applying it to ListCtrl, dragging the thumb box will have no effect. I tried my best to deal with it. Now I show you an alternate method.

I derive a new class from CListCtrl and handle WM_VSCROLL/WM_HSCROLL with a sbcode equal to SB_THUMBTRACK.

For example:

C++
LRESULT CListCtrlEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
 if(message==WM_VSCROLL||message==WM_HSCROLL)
 {
  WORD sbCode=LOWORD(wParam);
  if(sbCode==SB_THUMBTRACK
   ||sbCode==SB_THUMBPOSITION)
  {
   SCROLLINFO siv={0};
   siv.cbSize=sizeof(SCROLLINFO);
   siv.fMask=SIF_ALL;
   SCROLLINFO sih=siv;
   int nPos=HIWORD(wParam);
   CRect rcClient;
   GetClientRect(&rcClient);
   GetScrollInfo(SB_VERT,&siv);
   GetScrollInfo(SB_HORZ,&sih);
   SIZE sizeAll;
   if(sih.nPage==0) 
    sizeAll.cx=rcClient.right;
   else
    sizeAll.cx=rcClient.right*(sih.nMax+1)/sih.nPage ;
   if(siv.nPage==0)
    sizeAll.cy=rcClient.bottom;
   else
    sizeAll.cy=rcClient.bottom*(siv.nMax+1)/siv.nPage ;
   
   SIZE size={0,0};
   if(WM_VSCROLL==message)
   {
    size.cx=sizeAll.cx*sih.nPos/(sih.nMax+1);
    size.cy=sizeAll.cy*(nPos-siv.nPos)/(siv.nMax+1);
   }else
   {
    size.cx=sizeAll.cx*(nPos-sih.nPos)/(sih.nMax+1);
    size.cy=sizeAll.cy*siv.nPos/(siv.nMax+1);
   }
   Scroll(size);
   return 1;
  }
 }
 return CListCtrl::WindowProc(message, wParam, lParam);
}

Ok, that's all. Hope it will be helpful to you. Any suggestions will be welcome.

History

  • 2007-03-07
    • Fixed a bug of skinscrollwnd.cpp in which a wrong compare was done. Thanks to tHeWiZaRdOfDoS for reporting it to me.
  • 2007.1.23
    • Tested the project carefully and made some optimizations
  • 2007.1.22
    • Fixed a scrollbar's zero div bug, modified scrollbar's auto scroll codes
  • 2006.12.22
    • Modified code to apply it to combo ctrl
  • 2006.7.26
    • Showed a method for applying it to ListCtrl, etc.
  • 2006.7.12
    • Fixed a scrollbar's bug
  • 2006.7.9
    • Finished a primary frame

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Junior)
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: how to increase the width of vertical and horizontal scrollbar Pin
flyhigh17-Nov-07 14:34
professionalflyhigh17-Nov-07 14:34 
GeneralAdvice:remove OnTimer() and Add VScroll() & HScroll() message reflecting[modified] Pin
cbntrt6-Oct-07 0:13
cbntrt6-Oct-07 0:13 
GeneralRe: Advice:remove OnTimer() and Add VScroll() & HScroll() message reflecting[modified] Pin
flyhigh7-Oct-07 14:39
professionalflyhigh7-Oct-07 14:39 
GeneralRe: Advice:remove OnTimer() and Add VScroll() & HScroll() message reflecting[modified] Pin
cbntrt8-Oct-07 19:05
cbntrt8-Oct-07 19:05 
GeneralRe: Advice:remove OnTimer() and Add VScroll() & HScroll() message reflecting[modified] Pin
flyhigh8-Oct-07 20:37
professionalflyhigh8-Oct-07 20:37 
GeneralRe: Advice:remove OnTimer() and Add VScroll() & HScroll() message reflecting[modified] Pin
cbntrt8-Oct-07 22:12
cbntrt8-Oct-07 22:12 
GeneralRe: Advice:remove OnTimer() and Add VScroll() & HScroll() message reflecting[modified] Pin
flyhigh9-Oct-07 23:25
professionalflyhigh9-Oct-07 23:25 
NewsAdvice:remove OnTimer() and Add VScroll() & HScroll() message reflecting[modified] Pin
cbntrt5-Oct-07 23:14
cbntrt5-Oct-07 23:14 
code:
in skinscrollbar.h:
add:
<br />
	afx_msg void VScroll(UINT nSBCode, UINT nPos);<br />
	afx_msg void HScroll(UINT nSBCode, UINT nPos);<br />
	DECLARE_MESSAGE_MAP()<br />
<br />

in skinscrollbar.cpp:
add:
<br />
//      ON_WM_TIMER()//It looks ugly,so I want to remove it from your <br />
//                      beatiful code.<br />
        ON_WM_SIZE()//newly modified in its function<br />
	ON_WM_VSCROLL_REFLECT()//newly added<br />
	ON_WM_HSCROLL_REFLECT()//newly added<br />
END_MESSAGE_MAP()<br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />
// CSkinScrollBar message handlers<br />
<br />
<br />
void CSkinScrollBar::OnSize(UINT nType, int cx, int cy) <br />
{<br />
	CScrollBar::OnSize(nType, cx, cy);<br />
	<br />
	// TODO: Add your message handler code here<br />
	m_nHei=IsVertical()?cy:cx;<br />
<br />
	SCROLLINFO si={0};// newly added<br />
	si.cbSize=sizeof(si);// newly added<br />
	si.fMask=SIF_ALL;//newly added<br />
	si.nMax=100;//newly added<br />
	si.nMin=0;//newly added<br />
	si.nPage=10;//newly added<br />
	si.nPos=5;//newly added<br />
	SetScrollInfo(&si);//newly added.certainly,these can be improved by <br />
                           //using member variables m_nRangeMin and <br />
                           //m_nRangeMax to replace 0 and 100.<br />
                           //that is:min->0,max->100.and initialize them in <br />
                           //constructor.<br />
}<br />
<br />
<br />
<br />
//DEL void CSkinScrollBar::OnTimer(UINT nIDEvent)//It looks so unpleasant!! <br />
//DEL {<br />
//DEL // TODO: Add your message handler code here and/or call default<br />
//DEL 	if(nIDEvent==TIMERID_DELAY)<br />
//DEL 	{<br />
//DEL 		m_bNotify=TRUE;<br />
//DEL 		nIDEvent=TIMERID_NOTIFY;<br />
//DEL 		KillTimer(TIMERID_DELAY);<br />
//DEL 		SetTimer(TIMERID_NOTIFY,TIME_INTER,NULL);<br />
//DEL 	}<br />
//DEL 	if(nIDEvent==TIMERID_NOTIFY && !m_bPause)<br />
//DEL 	{<br />
//DEL 		ASSERT(m_uClicked!=-1 && m_uClicked!=SB_THUMBTRACK);<br />
//DEL 		<br />
//DEL 		switch(m_uClicked)<br />
//DEL 		{<br />
//DEL 		case SB_LINEUP:<br />
//DEL 			if(m_si.nPos==m_si.nMin)<br />
//DEL 			{<br />
//DEL 				KillTimer(TIMERID_NOTIFY);<br />
//DEL 				break;<br />
//DEL 			}<br />
//DEL GetParent()->SendMessage(IsVerticalWM_VSCROLL:WM_HSCROLL,MAKELONG//////(SB_LINEUP,0),(LPARAM)m_hWnd);		break;<br />
//DEL 		case SB_LINEDOWN:<br />
//DEL 			if(m_si.nPos==m_si.nMax)<br />
//DEL 			{<br />
//DEL 				KillTimer(TIMERID_NOTIFY);<br />
//DEL 				break;<br />
//DEL 			}<br />
//DEL 			GetParent()->SendMessage(IsVertical()?WM_VSCROLL:WM_HSCROLL,MAKELONG(SB_LINEDOWN,0),(LPARAM)m_hWnd);<br />
//DEL 			break;<br />
//DEL 		case SB_PAGEUP:<br />
//DEL 		case SB_PAGEDOWN:<br />
//DEL 			{<br />
//DEL 				CPoint pt;<br />
//DEL 				GetCursorPos(&pt);<br />
//DEL 				ScreenToClient(&pt);<br />
//DEL 				CRect rc=GetRect(SB_THUMBTRACK);<br />
//DEL 				if(rc.PtInRect(pt))<br />
//DEL 				{<br />
//DEL 					KillTimer(TIMERID_NOTIFY);<br />
//DEL 					break;<br />
//DEL 				}<br />
//DEL 				GetParent()->SendMessage(IsVertical()?WM_VSCROLL:WM_HSCROLL,MAKELONG(m_uClicked,0),(LPARAM)m_hWnd);<br />
//DEL 			}<br />
//DEL 			break;<br />
//DEL 		default:<br />
//DEL 			ASSERT(FALSE);<br />
//DEL 			break;<br />
//DEL 		}<br />
//DEL 	}*/<br />
//DEL }<br />
<br />
<br />
void CSkinScrollBar::VScroll(UINT nSBCode, UINT nPos) <br />
{<br />
	// TODO: Add your message handler code here<br />
	SCROLLINFO si={0};<br />
	si.fMask=SIF_ALL;<br />
	GetScrollInfo(&si,SIF_ALL);<br />
	switch(nSBCode)<br />
	{<br />
	case SB_LINEUP:<br />
		si.nPos--;<br />
		break;<br />
	case SB_LINEDOWN:<br />
		si.nPos++;<br />
		break;<br />
	case SB_PAGEUP:<br />
		si.nPos-=si.nPage;<br />
		break;<br />
	case SB_PAGEDOWN:<br />
		si.nPos+=si.nPage;<br />
		break;<br />
	case SB_THUMBTRACK:<br />
		si.nPos=nPos;<br />
		break;<br />
	}<br />
	if(si.nPos>(int)(si.nMax-si.nMin-si.nPage+1)) si.nPos=si.nMax-si.nMin-si.nPage+1;<br />
	if(si.nPos<si.nMin) si.nPos=si.nMin;<br />
	si.fMask=SIF_POS;<br />
	SetScrollInfo(&si);<br />
	TRACE("\nPos=%d",si.nPos);	<br />
}<br />
<br />
void CSkinScrollBar::HScroll(UINT nSBCode, UINT nPos) <br />
{<br />
	// TODO: Add your message handler code here<br />
	SCROLLINFO si={0};<br />
	si.fMask=SIF_ALL;<br />
	GetScrollInfo(&si,SIF_ALL);<br />
	switch(nSBCode)<br />
	{<br />
	case SB_LINEUP:<br />
		si.nPos--;<br />
		break;<br />
	case SB_LINEDOWN:<br />
		si.nPos++;<br />
		break;<br />
	case SB_PAGEUP:<br />
		si.nPos-=si.nPage;<br />
		break;<br />
	case SB_PAGEDOWN:<br />
		si.nPos+=si.nPage;<br />
		break;<br />
	case SB_THUMBTRACK:<br />
		si.nPos=nPos;<br />
		break;<br />
	}<br />
	if(si.nPos>(int)(si.nMax-si.nMin-si.nPage+1)) si.nPos=si.nMax-si.nMin-si.nPage+1;<br />
	if(si.nPos<si.nMin) si.nPos=si.nMin;<br />
	si.fMask=SIF_POS;<br />
	SetScrollInfo(&si);<br />
	TRACE("\nPos=%d",si.nPos);	<br />
}<br />

in scrolldlg.h:
protected:<br />
	HICON m_hIcon;<br />
<br />
	// Generated message map functions<br />
	//{{AFX_MSG(CScrollDlg)<br />
	virtual BOOL OnInitDialog();<br />
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);<br />
	afx_msg void OnPaint();<br />
	afx_msg HCURSOR OnQueryDragIcon();<br />
	afx_msg void OnButton1();<br />
	afx_msg void OnButton2();<br />
	afx_msg void OnSize(UINT nType, int cx, int cy);<br />
//	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);//heavy onus !! <br />
//	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);//heavy onus !! <br />
	afx_msg void OnDestroy();<br />
	afx_msg void OnAbout();<br />
	afx_msg void OnButton3();<br />
	afx_msg void OnLcMode();<br />
	//}}AFX_MSG<br />
	DECLARE_MESSAGE_MAP()<br />
};

in scrolldlg.cpp:
// scrollDlg.cpp : implementation file<br />
};<br />
<br />
BEGIN_MESSAGE_MAP(CScrollDlg, CDialog)<br />
	//{{AFX_MSG_MAP(CScrollDlg)<br />
	ON_WM_SYSCOMMAND()<br />
	ON_WM_PAINT()<br />
	ON_WM_QUERYDRAGICON()<br />
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)<br />
	ON_BN_CLICKED(IDC_BUTTON2, OnButton2)<br />
	ON_WM_SIZE()//<br />
//      ON_WM_HSCROLL()//newly removed onus <br />
//      ON_WM_VSCROLL()//newly removed onus <br />
	ON_WM_DESTROY()<br />
	ON_BN_CLICKED(IDC_ABOUT, OnAbout)<br />
	ON_BN_CLICKED(IDC_BUTTON3, OnButton3)<br />
	ON_BN_CLICKED(IDC_LC_MODE, OnLcMode)<br />
	//}}AFX_MSG_MAP<br />
END_MESSAGE_MAP()<br />
<br />
/////////////////////////////////////////////////////////////////////////////<br />
// CScrollDlg message handlers<br />
<br />
BOOL CScrollDlg::OnInitDialog()<br />
{<br />
	CDialog::OnInitDialog();<br />
<br />
	// Add "About..." menu item to system menu.<br />
<br />
	// IDM_ABOUTBOX must be in the system command range.<br />
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);<br />
	ASSERT(IDM_ABOUTBOX < 0xF000);<br />
<br />
	CMenu* pSysMenu = GetSystemMenu(FALSE);<br />
	if (pSysMenu != NULL)<br />
	{<br />
		CString strAboutMenu;<br />
		strAboutMenu.LoadString(IDS_ABOUTBOX);<br />
		if (!strAboutMenu.IsEmpty())<br />
		{<br />
			pSysMenu->AppendMenu(MF_SEPARATOR);<br />
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);<br />
		}<br />
	}<br />
<br />
	// Set the icon for this dialog.  The framework does this automatically<br />
	//  when the application's main window is not a dialog<br />
	SetIcon(m_hIcon, TRUE);			// Set big icon<br />
	SetIcon(m_hIcon, FALSE);		// Set small icon<br />
	<br />
	// TODO: Add extra initialization here<br />
	CBitmap bmp;<br />
	bmp.LoadBitmap(IDB_BITMAP1);<br />
	BITMAP bm;<br />
	bmp.GetBitmap(&bm);<br />
	m_hBmpScrollBar=(HBITMAP)bmp.Detach();<br />
<br />
	SkinWndScroll(&m_ctrlTree,m_hBmpScrollBar);<br />
	SkinWndScroll(&m_ctrlList,m_hBmpScrollBar);<br />
	SkinWndScroll(&m_ctrlEdit,m_hBmpScrollBar);<br />
	SkinWndScroll(&m_ctrlRichEdit,m_hBmpScrollBar);<br />
	SkinWndScroll(&m_ctrlLC,m_hBmpScrollBar);<br />
	m_cbxTest.SkinScroll(m_hBmpScrollBar);<br />
	m_cbxTest2.SkinScroll(m_hBmpScrollBar);<br />
	m_ctrlScroll.SetBitmap(m_hBmpScrollBar);<br />
//      SCROLLINFO si={0};// newly removed onus <br />
//	si.cbSize=sizeof(si);// newly removed onus <br />
//	si.fMask=SIF_ALL;//newly removed onus <br />
//	si.nMax=100;//newly removed onus <br />
//	si.nMin=0;//newly removed onus <br />
//	si.nPage=10;//newly removed onus <br />
//	si.nPos=5;//newly removed onus <br />
//	SetScrollInfo(&si);//newly removed to reduce the heavy work that  its parent dialog must do.<br />
//<br />
	m_ctrlLC.InsertColumn(0,"col1",0,80);<br />
	m_ctrlLC.InsertColumn(1,"col2",0,80);<br />
	char szbuf[50];<br />
	for(int i=0;i<50;i++)<br />
	{<br />
		sprintf(szbuf,"item%d_1",i);<br />
		m_ctrlLC.InsertItem(i,szbuf);<br />
		sprintf(szbuf,"item%d_2",i);<br />
		m_ctrlLC.SetItemText(i,1,szbuf);<br />
	}<br />
	return TRUE;  // return TRUE  unless you set the focus to a control<br />
}<br />
<br />
<br />
//DEL void CScrollDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) <br />
//DEL {<br />
//DEL 	if(	pScrollBar->m_hWnd==m_ctrlScroll.m_hWnd)<br />
//DEL 	{<br />
//DEL 		SCROLLINFO si;<br />
//DEL 		si.fMask=SIF_ALL;<br />
//DEL 		m_ctrlScroll.GetScrollInfo(&si,SIF_ALL);<br />
//DEL 		switch(nSBCode)<br />
//DEL 		{<br />
//DEL 		case SB_LINEUP:<br />
//DEL 			si.nPos--;<br />
//DEL 			break;<br />
//DEL 		case SB_LINEDOWN:<br />
//DEL 			si.nPos++;<br />
//DEL 			break;<br />
//DEL 		case SB_PAGEUP:<br />
//DEL 			si.nPos-=si.nPage;<br />
//DEL 			break;<br />
//DEL 		case SB_PAGEDOWN:<br />
//DEL 			si.nPos+=si.nPage;<br />
//DEL 			break;<br />
//DEL 		}<br />
//DEL 		if(si.nPos>(int)(si.nMax-si.nMin-si.nPage+1)) si.nPos=si.nMax-si.nMin-si.nPage+1;<br />
//DEL 		if(si.nPos<si.nMin) si.nPos=si.nMin;<br />
//DEL 		m_ctrlScroll.SetScrollInfo(&si);<br />
//DEL 	}<br />
//DEL }<br />
<br />
//DEL void CScrollDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) <br />
//DEL {<br />
//DEL /*	if(	pScrollBar->m_hWnd==m_ctrlScroll.m_hWnd)<br />
//DEL 	{<br />
//DEL 		SCROLLINFO si;<br />
//DEL 		si.fMask=SIF_ALL;<br />
//DEL 		m_ctrlScroll.GetScrollInfo(&si,SIF_ALL);<br />
//DEL 		switch(nSBCode)<br />
//DEL 		{<br />
//DEL 		case SB_LINEUP:<br />
//DEL 			si.nPos--;<br />
//DEL 			break;<br />
//DEL 		case SB_LINEDOWN:<br />
//DEL 			si.nPos++;<br />
//DEL 			break;<br />
//DEL 		case SB_PAGEUP:<br />
//DEL 			si.nPos-=si.nPage;<br />
//DEL 			break;<br />
//DEL 		case SB_PAGEDOWN:<br />
//DEL 			si.nPos+=si.nPage;<br />
//DEL 			break;<br />
//DEL 		case SB_THUMBTRACK:<br />
//DEL 			si.nPos=nPos;<br />
//DEL 			break;<br />
//DEL 		}<br />
//DEL 		if(si.nPos>(int)(si.nMax-si.nMin-si.nPage+1)) si.nPos=si.nMax-si.nMin-si.nPage+1;<br />
//DEL 		if(si.nPos<si.nMin) si.nPos=si.nMin;<br />
//DEL 		si.fMask=SIF_POS;<br />
//DEL 		m_ctrlScroll.SetScrollInfo(&si);<br />
//DEL 		TRACE("\nPos=%d",si.nPos);<br />
//DEL 	}<br />
//DEL 	*/<br />
//DEL }<br />
<br />
<br />
<br />



-- modified at 5:26 Saturday 6th October, 2007
QuestionHow to use this class without border? Pin
HoiN\ kyung-joon16-Apr-07 18:25
HoiN\ kyung-joon16-Apr-07 18:25 
AnswerRe: How to use this class without border? Pin
flyhigh19-Apr-07 1:31
professionalflyhigh19-Apr-07 1:31 
GeneralI wand to give your advice. Pin
HoiN\ kyung-joon16-Apr-07 16:40
HoiN\ kyung-joon16-Apr-07 16:40 
GeneralRe: I wand to give your advice. Pin
flyhigh16-Apr-07 17:29
professionalflyhigh16-Apr-07 17:29 
GeneralRe: I wand to give your advice. Pin
Jonghwa, Cho19-Aug-07 14:49
Jonghwa, Cho19-Aug-07 14:49 
QuestionProblems and a possible bug Pin
tHeWiZaRdOfDoS2-Mar-07 4:35
tHeWiZaRdOfDoS2-Mar-07 4:35 
AnswerRe: Problems and a possible bug Pin
flyhigh5-Mar-07 21:36
professionalflyhigh5-Mar-07 21:36 
Generalvery perfect! ye~~~ye~~~~~ Pin
Young E30-Jan-07 15:38
Young E30-Jan-07 15:38 
GeneralThank you! Pin
flute99924-Jan-07 19:27
flute99924-Jan-07 19:27 
Questionthumb size Pin
Babbage_15-Jan-07 21:19
Babbage_15-Jan-07 21:19 
AnswerRe: thumb size Pin
flyhigh17-Jan-07 21:25
professionalflyhigh17-Jan-07 21:25 
GeneralRe: thumb size Pin
Babbage_18-Jan-07 1:56
Babbage_18-Jan-07 1:56 
GeneralRe: thumb size Pin
flyhigh22-Jan-07 21:18
professionalflyhigh22-Jan-07 21:18 
GeneralRe: thumb size Pin
Babbage_23-Jan-07 7:54
Babbage_23-Jan-07 7:54 
Questionresize error Pin
xunmengfeng11-Jan-07 15:37
xunmengfeng11-Jan-07 15:37 
AnswerRe: resize error Pin
flyhigh11-Jan-07 15:52
professionalflyhigh11-Jan-07 15:52 
GeneralError:Integer division by zero. Pin
Tee Moore29-Dec-06 22:07
Tee Moore29-Dec-06 22:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.