⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spinbuttonctrlex.cpp

📁 UHF RFID Reader Program
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		dc.SelectObject(pOldBrush);
	}

	void CSpinButtonCtrlEx::DrawPressedRect(CDC &dc, const CRect &rctToDown) const
	{

		CRect 	rctDown=rctToDown;
		HPEN hOldPen;

		//Offset bitmap one pixel left and down

		dc.BitBlt(rctDown.left+1,rctDown.top+1,
			rctDown.Width()-1,rctDown.Height()-1,&dc,
			rctDown.left,rctDown.top,SRCCOPY);

		// Draw the border of pressed button
		rctDown.bottom-=1;

		hOldPen = (HPEN)SelectObject(dc.m_hDC,m_penShadow);
		dc.MoveTo(rctDown.left,rctDown.bottom-1);
		dc.LineTo(rctDown.left,rctDown.top);
		dc.LineTo(rctDown.right-1,rctDown.top);

		SelectObject(dc.m_hDC,m_penLight);
		dc.LineTo(rctDown.right-1,rctDown.bottom);
		dc.LineTo(rctDown.left-1,rctDown.bottom);


		SelectObject(dc.m_hDC,m_penDarkShadow);
		dc.MoveTo(rctDown.left+1,rctDown.bottom-2);
		dc.LineTo(rctDown.left+1,rctDown.top+1);
		dc.LineTo(rctDown.right-2,rctDown.top+1);

		SelectObject(dc.m_hDC,m_penLightShadow);
		dc.LineTo(rctDown.right-2,rctDown.bottom-1);
		dc.LineTo(rctDown.left,rctDown.bottom-1);

		SelectObject(dc.m_hDC,m_penButtonFace);
		dc.MoveTo(rctDown.left+2,rctDown.bottom-2);
		dc.LineTo(rctDown.left+2,rctDown.top+2);
		dc.LineTo(rctDown.right-2,rctDown.top+2);



		SelectObject(dc.m_hDC,hOldPen);


	}

	void CSpinButtonCtrlEx::Init()
	{ 
		//We need to know m_hWndBuddy even if UDS_WRAP style applied, to fix bug
		// with possible incorrect Z-order of buddy/spin
		m_hWndBuddy=(HWND)::SendMessage(m_hWnd, UDM_GETBUDDY, 0, 0l);

		DWORD dwStyle=::GetWindowLong(m_hWnd,GWL_STYLE);
		if(dwStyle & UDS_WRAP)
			m_bAutoDisable=false; //if the UDS_WRAP style was applied, we can't disable arrows

		// The m_bAutoDisable can also  be set from outside using SetAutoDisable method;
		if(m_bAutoDisable) 
		{
			//Determine the orientation and alignment of this CSpinButtonCtrlEx
			if(dwStyle & UDS_ALIGNRIGHT )
				m_nSpinAlign=OnRightInside;
			else
			{
				if(dwStyle & UDS_ALIGNLEFT)
				{
					m_nSpinAlign=OnLeftInside;

				}
			}
			if(dwStyle & UDS_HORZ)
				m_bVertical=false;


			//Determine the control's limits and direction of increasing of it's position
			GetRange32(m_nMinPos,m_nMaxPos);	
			if( m_nMinPos < m_nMaxPos)
				m_bDefaultDirection =false;
			else
			{
				int nTemp = m_nMinPos;
				m_nMinPos = m_nMaxPos;
				m_nMaxPos=nTemp;
			}

			GetClientRect(&m_rctClient);

			m_nPrevPos = GetPos();

			//Determine the control's initial enable/disable state
			m_nSpinState = BothEnable;
			if(m_nPrevPos == m_nMinPos)
				m_nSpinState = DisableLeft;
			else
			{
				if(m_nPrevPos == m_nMaxPos)
					m_nSpinState = DisableRight;

			}

			if(::IsWindow(m_hWndBuddy))
			{
				TCHAR buf[5];
				::GetClassName(m_hWndBuddy,buf,sizeof(buf)/sizeof(buf[0]));

				if(!_tcscmp(buf,_T("Edit")))
				{
					//The class  of buddy is Edit
					m_bBuddyIsEdit=true;

					//I need to update the enabled/disabled state of CSpinButtonCtrlEx
					//when contents of buddy window is changing.
					//For instance, if user enters into buddy window the value greater
					//than upper possible limit - it is obvious that the increasing 
					//arrow should switch to disable state.
					//The best way to do it is to create WH_CALLWNDPROC hook 
					//and test within it if EN_UPDATE message came from buddy window
					//Another posibility- keyboard hook, but then the user can foolish 
					//the control, using clipboard Copy/Cut/Paste functions.

					//Test if WH_CALLWNDPROC hook already was installed.
					// If no, set up it.
					if(ghHook==NULL)
						ghHook=SetWindowsHookEx(WH_CALLWNDPROC,FilterBuddyMsgProc,NULL, //WH_GETMESSAGE
						GetCurrentThreadId());
					//As so I use a single WH_CALLWNDPROC hook for all existing in
					//an application CSpinButtonCtrlEx controls, I need to distinguish
					// between these controls in the static FilterBuddyMsgProc.
					//For this purpose I use static std:map<HWND,HWND> gHandleMap

					//Try to find m_hWndBuddy in the gHandleMap
					HWNDMAP::iterator iterHwnd=gHandleMap.find(m_hWndBuddy);
					if(iterHwnd != gHandleMap.end())
					{
						if((*iterHwnd).second != m_hWnd)
						{
							//If in the gHandleMap already defined  another CSpinButtonCtrlEx
							//for that buddy (m_hWndBuddy), then redefine it .
							gHandleMap.erase(iterHwnd);	
							gHandleMap.insert(HWNDMAP::value_type(m_hWndBuddy,m_hWnd));
						}
					}
					else
						//If the CSpinButtonCtrlEx assosiated with
						//m_hWndBuddy is not found in the gHandleMap, then add it.
						gHandleMap.insert(HWNDMAP::value_type(m_hWndBuddy,m_hWnd));
				}
			}
			Invalidate(FALSE);
		}
	}

	BOOL CSpinButtonCtrlEx::OnDeltapos(NMHDR* pNMHDR, LRESULT* pResult) 
	{
		if(m_bAutoDisable)
		{
			NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR;

			int nNextPos=pNMUpDown->iPos+pNMUpDown->iDelta;

			//Determine the enable/disable state of CSpinButtonCtrlEx
			if(nNextPos > m_nMaxPos)
				nNextPos = m_nMaxPos;
			else
			{
				if(nNextPos < m_nMinPos)
					nNextPos = m_nMinPos;
			}

			if(m_nPrevPos!=nNextPos)
			{
				if(pNMUpDown->iDelta)
					m_bActiveSpinPressed=true;

				if(nNextPos  <m_nMaxPos && nNextPos >m_nMinPos)
				{
					m_nSpinState = BothEnable;
				}
				else
				{
					if(nNextPos == m_nMaxPos)
					{
						if(m_nMaxPos != m_nMinPos)
						{
							m_nSpinState=DisableRight;
							m_bActiveSpinPressed=false;
						}
						else
						{
							m_nSpinState = BothDisable;
							m_bActiveSpinPressed=false;
						}
					}
					else
					{
						if(nNextPos == m_nMinPos)
						{
							m_nSpinState=DisableLeft;
							m_bActiveSpinPressed=false;
						}
					}
				}
				m_nPrevPos=nNextPos;
				Invalidate(FALSE);

				//Let the Windows process UDN_DELTAPOS too
				*pResult = 0;
				return FALSE;
			}
			else
			{
				//If the next position of control is the same as current,
				//what can happen when user clicked the disable arrow,
				//then eat UDN_DELTAPOS
				*pResult = 1;
				return TRUE;
			}
		}
		else
		{ 
			//Let the Windows process UDN_DELTAPOS
			*pResult = 0;
			return FALSE;
		}
	}


	LRESULT CSpinButtonCtrlEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
	{
		//Let the Windows do it's work 
		LRESULT nRet = CSpinButtonCtrl::WindowProc(message, wParam, lParam);

		switch(message)
		{
		case UDM_SETRANGE32:
		case UDM_SETRANGE: 
			//Need to reinit CSpinButtonCtrlEx, as so the
			//limits probably changed
			Init();
			break;


		case UDM_SETBUDDY :
			//Need to reinit CSpinButtonCtrlEx, as so the
			//buddy changed
			CleanUpHook();
			Init();
			//If buddy window(m_hWndBuddy) is placed after this 
			//CSpinButtonCtrlEx in Z-order , then m_hWndBuddywindow will 
			//get WM_PAINT message after  this CSpinButtonCtrlEx control 
			//and in case CSpinButtonCtrlEx is attached to buddy,
			// it will be overpainted by buddy's border
			//This undocumented bug persist for CSpinButtonCtrl as well.
			//
			//To reproduce it create on dialog template attached
			//CSpinButtonCtrl control and CEdit control and make
			//tab order so, that for CSpinButtonCtrl tab position 
			//was less then for CEdit;
			//Then in OnInitDiaolg call SetBuddy(pointerToEdit) function 
			//of CSpinButtonCtrl.
			//
			//
			//To work around this simply place CSpinButtonCtrl
			//after it's buddy in Z-order. 
			if(::IsWindow(m_hWndBuddy))
				::SetWindowPos(m_hWnd,m_hWndBuddy,0,0,0,0,
				SWP_NOMOVE|SWP_NOSIZE);

			break;
		}
		return nRet;

	}

	void CSpinButtonCtrlEx::CleanUpHook() const
	{
		if(m_bBuddyIsEdit)
		{
			//If the buddy is edit, then try to find out if
			//it was added to gHandleMap.
			HWNDMAP::iterator iterHwnd=gHandleMap.find(m_hWndBuddy);
			if(iterHwnd != gHandleMap.end() && (*iterHwnd).second == m_hWnd)
			{
				//If m_hWndBuddy found and is assosiated with current window,
				//then delete it from gHandleMap.
				iterHwnd = gHandleMap.erase(iterHwnd);
				if(!gHandleMap.size() && ghHook!=NULL)
				{
					//If just deleted from the gHandleMap m_hWndBuddy was
					//the last for current application,
					//then remove a hook procedure. 
					UnhookWindowsHookEx( ghHook);
					ghHook=NULL;
				}
			}
		}
	}

	void CSpinButtonCtrlEx::OnLButtonDown(UINT nFlags, CPoint point) 
	{
		m_rctIsPressed.SetRectEmpty();
		CSpinButtonCtrl::OnLButtonDown(nFlags, point);
	}

	BOOL CSpinButtonCtrlEx::OnEraseBkgnd(CDC* pDC) 
	{
		return TRUE	; //Get rid of flickering

	}

	void CSpinButtonCtrlEx::OnLButtonUp(UINT nFlags, CPoint point) 
	{
		Invalidate();	
		UpdateWindow();
		CSpinButtonCtrl::OnLButtonUp(nFlags, point);
	}

	bool CSpinButtonCtrlEx::SetAutoDisable(bool bSetOn)
	{
		// User should have an opportunity to swith on/off the custom
		//behavior of  the CSpinButtonCtrlEx control.

		bool bPrev = m_bAutoDisable;
		m_bAutoDisable = bSetOn;
		Init();

		return bPrev;
	}

	LRESULT CALLBACK FilterBuddyMsgProc(  int code,  WPARAM wParam,  LPARAM lParam )
	{
		CWPSTRUCT* pData=reinterpret_cast<CWPSTRUCT*>(lParam);
		if(WM_COMMAND==pData->message && EN_UPDATE==HIWORD(pData->wParam))
		{
			//If the incoming message is EN_UPDATE
			HWNDMAP::iterator iterHwnd=gHandleMap.find(reinterpret_cast<HWND>(pData->lParam));
			if(iterHwnd != gHandleMap.end())
			{
				//The incoming EN_UPDATE message has been sent
				//to the edit control, defined in the gHandleMap.

				//So get the value, entered into the edit control
				//and send it to the CSpinButtonCtrlEx, assosiated
				//with the edit control.
				CString strText;
				int nLen=::GetWindowTextLength((*iterHwnd).first);
				::GetWindowText((*iterHwnd).first,strText.GetBufferSetLength(nLen),nLen+1);
				strText.ReleaseBuffer();

				//In case UDS_NOTHOUSANDS style not applied
				//we have to delete thousands delimiter from string
				strText.Remove((TCHAR)0xA0);

				NMUPDOWN nmUpDn;
				nmUpDn.iDelta=0;
				nmUpDn.iPos=_tstoi(strText);
				nmUpDn.hdr.code=UDN_DELTAPOS;
				nmUpDn.hdr.hwndFrom=(*iterHwnd).second;
				nmUpDn.hdr.idFrom=::GetDlgCtrlID((*iterHwnd).second);

				HWND hWndSpinParent=::GetParent((*iterHwnd).second);
				::SendMessage(::GetParent((*iterHwnd).second),
					WM_NOTIFY,(WPARAM)nmUpDn.hdr.idFrom,
					(LPARAM)&nmUpDn);
			}
		}
		return CallNextHookEx(ghHook,code,wParam,lParam);
	}

	void CSpinButtonCtrlEx::OnDestroy() 
	{
		//Remove current CSpinButtonCtrlEx control from the gHandleMap and
		//if it is the last control, defined in the gHandleMap
		//then remove a hook procedure. 
		CleanUpHook();

		CSpinButtonCtrl::OnDestroy();
	}

#endif
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -