Ein CEdit-Control mit nem Button?



  • na ich werd da mal nachkucken... meld mich dann wieder wenn ich etwas gefunden habe...



  • Achja, hast du schon mal bei Codeproject geguckt? Vielleicht gibt es da was ähnliches. 🙂



  • 😃

    Habe es erstmal hinbekommen... habe mir einen Teil des CEdit-Fensters mit create reserviert und dann konnte ich da drinnen rummalen. mit den ereignissen LButtondown und LButtonright kann ich nun den Status ändern und erhalte somit nen Button. ist zwar bestimmt nicht so ganz die feine art denke ich mal, aber es geht erstmal. hem mich würde mal interessieren ob man nicht gleich ein Button in diesen bereich integrieren kann? Hier ein wenig Quelltext:

    oid CIconWnd::DrawButton(int ButtonState)
    {
    
    	CPaintDC dc( this );
    	CRect rect;
    	GetClientRect( &rect );
    
    	dc.FillSolidRect( rect, GetSysColor(COLOR_WINDOW) );
    
    	CRect DrawRect(rect);
    	DrawRect.OffsetRect(0 - rect.left, 0 - rect.top);
    	CWindowDC WndDC(this);     // get the DC for drawing
    
    	CDC MemDC;
    	MemDC.CreateCompatibleDC(&WndDC);
    	int savedDC = MemDC.SaveDC();
    	CBitmap Bitmap;
    	Bitmap.CreateCompatibleBitmap(&WndDC, rect.Width(), rect.Height());
    	MemDC.SelectObject(&Bitmap);
    
    	CBrush theBrush(/*HS_DIAGCROSS,*/ GetSysColor(COLOR_3DFACE));
    	CPoint BrushOrg;
    	CPoint Origin = WndDC.GetBrushOrg();
    	BrushOrg.x = (8 - (rect.left - Origin.x) % 8);
    	BrushOrg.y = (8 - (rect.top - Origin.y) % 8);
    	MemDC.SetBrushOrg(BrushOrg);
    
    	MemDC.SelectObject(&theBrush);
    	MemDC.FillRect(&DrawRect, &theBrush);
    
    	// Drawing the icon
    	int width = GetSystemMetrics( SM_CXSMICON );
    	int height = GetSystemMetrics( SM_CYSMICON );
    
    	switch(ButtonState)
    	{
    	case 0:
    		{
    			MemDC.DrawEdge(DrawRect, EDGE_RAISED, BF_RECT);
    			WndDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &MemDC,
    							0, 0, SRCCOPY);		
    			MemDC.RestoreDC(savedDC);
    			Bitmap.DeleteObject();
    			::DrawIconEx( dc.m_hDC, 2, 1, m_icon, width, height, 0, NULL, DI_NORMAL );
    			break;
    		}
    
    	case 1:
    		{
    			CPen thePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
    			CPen *pOldPen = MemDC.SelectObject(&thePen);
    			MemDC.Rectangle(DrawRect);
    			MemDC.SelectObject(pOldPen);
    			thePen.DeleteObject();
    			WndDC.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &MemDC,
    							0, 0, SRCCOPY);		
    
    			MemDC.RestoreDC(savedDC);
    			Bitmap.DeleteObject();
    			::DrawIconEx( dc.m_hDC, 2, 1, m_icon, width, height, 0, NULL, DI_NORMAL);
    
    			break;
    		}
    	}
    
    }
    
    void CIconWnd::OnLButtonUp(UINT nFlags, CPoint point) 
    {
    	// TODO: Add your message handler code here and/or call default
    
    	CStatic::OnLButtonDown(nFlags, point);
    
    	ButtonState = 0;
    	if (m_icon)
    		DrawButton(ButtonState);
    	RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW/* | RDW_ERASE*/);
    }
    
    void CIconWnd::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    	// TODO: Add your message handler code here and/or call default
    
    	CStatic::OnLButtonDown(nFlags, point);
    
    	ButtonState = 1;
    	if (m_icon)
    		DrawButton(ButtonState);
    	RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW/* | RDW_ERASE*/);
    }
    


  • Du kannst doch jedes Control mit Create erstellen, also auch einen Button.
    Ich hab mich da bisher erfolgreich drum gedrückt, deswegen müßte ich auch suchen.

    Ich würde es so versuchen:

    CButton* m_pBtn;
    pBtn->Create(...); // Musste nachgucken
    

    Verstanden, worauf ich hinaus will? Sonst muss ich mal nen Beitrag mit sowas suchen. 🙂



  • jap hab es heute nacht dann auch so probiert. hat auch ganz gut geklappt. Wäre ich mal nur früher darauf gekommen. Hätte mir bestimmt viele nerfen gespart... 😉

    Danke ....





  • warum setzt du den Button nicht einfach neben das Editfeld ? 😉



  • 1. Sieht häßlicher aus
    2. Wirkt nur bedingt zusammengehörend
    3. Wenn man erstmal was im Kopf hat...
    🙂



  • 4. Ist praktischer da man dann das ganze Control einsetzen kann ohne jedes mal den Button nebendran einzufügen 🙂



  • 🙂 ,

    hab es endlich geschafft. mein cedit kontroll mit nem button das jetzt ne folderauswahl aufruft und danach den pfad im cedit feld schreibt... im nachhinein frag ich mich nur - warun das so lange gedauert hatte bei mir.. es ist eigentlich ganz einfach... Habe auch gleich alles so gemacht das ich die visual styles von XP benutzen kann... das ganze besteht nun aus einer CXPBUTTON Klasse und ner CXPFolderEdit Klasse... beide gut gewürfelt und gezähmt ergeben mein CEditfeld mit browser button für Verzeichnisse... Und das schöne daran ist, dass ich die CXPButton klasse für alle Buttons verwenden kann... 🙂 🙂

    Danke an alle die mir dabei geholfen haben...

    Hier nun der Quellcode für alle die es Interessiert:

    #if !defined(AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_)
    #define AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    // XPBUTTON.h : header file
    //
    
    /////////////////////////////////////////////////////////////////////////////
    // CXPBUTTON window
    
    class CXPBUTTON : public CButton
    {
    	DECLARE_DYNAMIC(CXPBUTTON)	
    // Construction
    public:
    	CXPBUTTON();
    
    // Attributes
    public:
    
    // Operations
    public:
    
    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CXPBUTTON)
    	public:
    	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    	protected:
    	virtual void PreSubclassWindow();
    	//}}AFX_VIRTUAL
    
    // Implementation
    public:
    	void SetIcon(int hIcon, int Icon_Width, int Icon_Hight);
    
    	virtual ~CXPBUTTON();
    
    	void PrepareImageRect(HWND hButtonWnd, BOOL bHasTitle, RECT* rpItem, RECT* rpTitle,
    						  BOOL bIsPressed, DWORD dwWidth, DWORD dwHeight, RECT* rpImage);
    	void DrawTheIcon(HWND hButtonWnd, HDC* dc, BOOL bHasTitle, RECT* rpItem, RECT* rpTitle,
    					BOOL bIsPressed, BOOL bIsDisabled);
    
    	bool bMouseOverButton;
    
    	HICON	hIcon;
    	int		Icon_W;
    	int		Icon_H;
    
    private:
    	CXPTheme* m_pTheme;
    
    	// Generated message map functions
    protected:
    	//{{AFX_MSG(CXPBUTTON)
    	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    	//}}AFX_MSG
    	LONG OnMouseLeave(WPARAM wParam, LPARAM lParam);
    
    	DECLARE_MESSAGE_MAP()
    };
    
    /////////////////////////////////////////////////////////////////////////////
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    
    #endif // !defined(AFX_XPBUTTON_H__9AE4DC26_E531_4C94_BF39_F53EE333DF78__INCLUDED_)
    
    // XPBUTTON.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "XPStyle.h"
    #include "XPBUTTON.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    #define ODS_NOFOCUSRECT     0x0200
    
    /////////////////////////////////////////////////////////////////////////////
    // CXPBUTTON
    IMPLEMENT_DYNAMIC(CXPBUTTON, CButton)
    
    CXPBUTTON::CXPBUTTON(): m_pTheme(NULL) 
    
    {
    	bMouseOverButton = false;
    
    	hIcon = NULL;
    }
    
    CXPBUTTON::~CXPBUTTON()
    {
    	delete m_pTheme;
    }
    
    BEGIN_MESSAGE_MAP(CXPBUTTON, CButton)
    	//{{AFX_MSG_MAP(CXPBUTTON)
    	ON_WM_ERASEBKGND()
    	ON_WM_MOUSEMOVE()
    	//}}AFX_MSG_MAP
    	ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CXPBUTTON message handlers
    
    void CXPBUTTON::PrepareImageRect(HWND hButtonWnd, BOOL bHasTitle, RECT* rpItem, RECT* rpTitle,
    					  BOOL bIsPressed, DWORD dwWidth, DWORD dwHeight, RECT* rpImage)
    {
    	RECT rBtn;
    
    	CopyRect(rpImage, rpItem);
    
    	GetClientRect(&rBtn);
    	if (bHasTitle == FALSE)
    	{
    		// Center image horizontally
    		LONG rpImageWidth = rpImage->right - rpImage->left;
    		rpImage->left += ((rpImageWidth - (long)dwWidth)/2);
    		LONG rpImageHeight = rpImage->bottom - rpImage->top;
    		rpImage->top += ((rpImageHeight - (long)dwHeight)/2);
    	}
    	else
    	{
    		// Image must be placed just inside the focus rect
    		LONG rpTitleWidth = rpTitle->right - rpTitle->left;
    		rpTitle->right = rpTitleWidth - dwWidth - 14;
    		rpTitle->left = 14;
    		rpImage->left = rBtn.right - dwWidth - 14;
    		// Center image vertically
    		LONG rpImageHeight = rpImage->bottom - rpImage->top;
    		rpImage->top += ((rpImageHeight - (long)dwHeight)/2);
    	}
    
    	// If button is pressed then press image also
    	if (bIsPressed && !m_pTheme->IsAppThemed())
    		OffsetRect(rpImage, 1, 1);
    } // End of PrepareImageRect
    
    void CXPBUTTON::DrawTheIcon(HWND hButtonWnd, HDC* dc, BOOL bHasTitle, RECT* rpItem, RECT* rpTitle,
    				 BOOL bIsPressed, BOOL bIsDisabled)
    {
    	RECT	rImage;
    
    	PrepareImageRect(hButtonWnd, bHasTitle, rpItem, rpTitle, bIsPressed, Icon_W, Icon_H, &rImage);
    
    	DrawState(	*dc,
    				NULL,
    				NULL,
    				(LPARAM)hIcon,
    				0,
    				rImage.left,
    				rImage.top,
    				(rImage.right - rImage.left),
    				(rImage.bottom - rImage.top), 
    				(bIsDisabled ? DSS_DISABLED : DSS_NORMAL) | DST_ICON);
    } // End of DrawTheIcon
    
    void CXPBUTTON::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
    	// wird aufegrufen vom Framework wegen ownerdraw-style 
    
    	CDC dc; 
        dc.Attach(lpDrawItemStruct->hDC); 
        CString strCaption; 
        GetWindowText(strCaption); 
        if (m_pTheme->IsAppThemed())
    	{			
    		// button state
    		BOOL bIsPressed =	(lpDrawItemStruct->itemState & ODS_SELECTED);
    		BOOL bIsFocused  = (lpDrawItemStruct->itemState & ODS_FOCUS);
    		BOOL bIsDisabled = (lpDrawItemStruct->itemState & ODS_DISABLED);
    		BOOL bDrawFocusRect = !(lpDrawItemStruct->itemState & ODS_NOFOCUSRECT);
    
    		// Prepare draw... paint button background
    
    		DWORD state = (bIsPressed)?PBS_PRESSED:PBS_NORMAL;
    
    		if(state == PBS_NORMAL)
    		{
    			if(bIsFocused)
    				state = PBS_DEFAULTED;
    			if(bMouseOverButton)
    				state = PBS_HOT;
    		}
    
    		COLORREF crColor = GetSysColor(COLOR_BTNFACE);
    
    		HBRUSH	brBackground = CreateSolidBrush(crColor);
    
    		FillRect(dc, &lpDrawItemStruct->rcItem, brBackground);
    
    		DeleteObject(brBackground);
    
    		m_pTheme->DrawBackground(lpDrawItemStruct->hDC, BP_PUSHBUTTON, state,
    									&lpDrawItemStruct->rcItem, 0); 
    
    		// Read the button's title
    		char sTitle[100];
    		sTitle[0] = '\0';
    		GetWindowText(sTitle, 100);
    
    		RECT captionRect = lpDrawItemStruct->rcItem;
    
    		// Draw the icon
    		BOOL bHasTitle = (sTitle[0] != '\0');
    		if (!hIcon == NULL)
    			DrawTheIcon(GetSafeHwnd(), &lpDrawItemStruct->hDC, bHasTitle,
    						&lpDrawItemStruct->rcItem, &captionRect, bIsPressed, bIsDisabled);
    
    		// Write the button title (if any)
    			if (bHasTitle)
    			{// Draw the button's title
    
    				// Center text
    				RECT centerRect = captionRect;
    				DrawText(dc, sTitle, -1, &captionRect, DT_WORDBREAK | DT_CENTER | DT_CALCRECT);
    				LONG captionRectWidth = captionRect.right - captionRect.left;
    				LONG captionRectHeight = captionRect.bottom - captionRect.top;
    				LONG centerRectWidth = centerRect.right - centerRect.left;
    				LONG centerRectHeight = centerRect.bottom - centerRect.top;
    				OffsetRect(&captionRect, (centerRectWidth - captionRectWidth)/2, (centerRectHeight - captionRectHeight)/2);
    
    				if(m_pTheme->IsAppThemed())
    				{					
    					// convert title to UNICODE obviously you don't need to do this if you are a UNICODE app.
    					int nTextLen = strlen(sTitle); 
    					int mlen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char *)sTitle, nTextLen + 1, NULL, 0); 
    					WCHAR* output = new WCHAR[mlen];
    					if(output)
    					{
    						MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char *)sTitle, nTextLen + 1, output, mlen);
    						m_pTheme->DrawText(lpDrawItemStruct->hDC, BP_PUSHBUTTON, PBS_NORMAL,
    										output, wcslen(output),
    										DT_CENTER | DT_VCENTER | DT_SINGLELINE,
    										0, &captionRect);
    						delete output;
    					}
    				}
    			}
    
    		if (bIsFocused && bDrawFocusRect)
    		{
    			RECT focusRect =lpDrawItemStruct->rcItem;
    			InflateRect(&focusRect, -3, -3);
    			DrawFocusRect(dc, &focusRect);
    		}
    	}
        dc.Detach(); 
    }
    
    BOOL CXPBUTTON::OnEraseBkgnd(CDC* pDC) 
    {
    	// wir zeichnen nichts, weil wir das fenster mit den button 
        // komplett in DrawItem zeichnen 
        // ausserdem verhindern wir dadurch flickern da der standard hintergrund 
        // weiss gezeichnet wird 
    
        return TRUE;
    }
    
    void CXPBUTTON::PreSubclassWindow() 
    {
    	// TODO: Add your specialized code here and/or call the base class
    
    	 m_pTheme = new CXPTheme(GetSafeHwnd(), L"BUTTON"); 
    
    	CButton::PreSubclassWindow();
    }
    
    void CXPBUTTON::OnMouseMove(UINT nFlags, CPoint point) 
    {
    	// TODO: Add your message handler code here and/or call default
    
    	if(!bMouseOverButton)
    	{
    		bMouseOverButton = TRUE;
    
    		TRACKMOUSEEVENT trackmouseevent;
    		trackmouseevent.cbSize = sizeof(trackmouseevent);
    		trackmouseevent.dwFlags = TME_LEAVE;
    		trackmouseevent.hwndTrack = GetSafeHwnd();
    		trackmouseevent.dwHoverTime = 0;
    		_TrackMouseEvent(&trackmouseevent);
    
    		Invalidate(FALSE);
    	} 
    
    	CButton::OnMouseMove(nFlags, point);
    }
    
    LONG CXPBUTTON::OnMouseLeave(WPARAM wParam, LPARAM lParam) 
    {
    	bMouseOverButton = FALSE;
    
    	Invalidate(FALSE);
    
    	return 0;
    }
    
    void CXPBUTTON::SetIcon(int hIconID, int Icon_Width, int Icon_Hight)
    {
    	Icon_W = Icon_Width;
    	Icon_H = Icon_Hight;
    
    	hIcon = ( HICON ) ::LoadImage( AfxGetResourceHandle(),
    									MAKEINTRESOURCE(hIconID),
    									IMAGE_ICON,
    									Icon_Width,
    									Icon_Hight,
    									LR_LOADTRANSPARENT );
    }
    
    #if !defined(AFX_XPFOLDEREDIT_H__3985CDC8_0639_44E0_897D_DBFB1B5C06B2__INCLUDED_)
    #define AFX_XPFOLDEREDIT_H__3985CDC8_0639_44E0_897D_DBFB1B5C06B2__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    #include "XPBUTTON.h"
    #include "shlobj.h"
    
    // XPFolderEdit.h : header file
    //
    
    /////////////////////////////////////////////////////////////////////////////
    // CXPFolderEdit window
    
    class CXPFolderEdit : public CEdit
    {
    	DECLARE_DYNAMIC(CXPFolderEdit)
    
    // Construction
    public:
    	CXPFolderEdit();
    
    // Attributes
    public:
    
    // Operations
    public:
    
    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CXPFolderEdit)
    	protected:
    	virtual void PreSubclassWindow();
    	//}}AFX_VIRTUAL
    
    // Implementation
    public:
    	virtual ~CXPFolderEdit();
    
    	// Generated message map functions
    
    protected:
    	CXPBUTTON	m_Button;
    	CRect		m_ButtonRect;
    	HCURSOR		hCursor;
        HICON		hIcon;
    
    	//{{AFX_MSG(CXPFolderEdit)
    	afx_msg void OnMyButton();
    	//}}AFX_MSG
    
    	DECLARE_MESSAGE_MAP()
    private:
    
    };
    
    /////////////////////////////////////////////////////////////////////////////
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    
    #endif // !defined(AFX_XPFOLDEREDIT_H__3985CDC8_0639_44E0_897D_DBFB1B5C06B2__INCLUDED_)
    
    // XPFolderEdit.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "XPStyle.h"
    #include "XPFolderEdit.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // CXPFolderEdit
    
    IMPLEMENT_DYNAMIC(CXPFolderEdit, CEdit)
    
    CXPFolderEdit::CXPFolderEdit()
    {
    }
    
    CXPFolderEdit::~CXPFolderEdit()
    {
    }
    
    BEGIN_MESSAGE_MAP(CXPFolderEdit, CEdit)
    	//{{AFX_MSG_MAP(CXPFolderEdit)
    	ON_BN_CLICKED(MyButton, OnMyButton)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CXPFolderEdit message handlers
    
    void CXPFolderEdit::PreSubclassWindow() 
    {
    	// TODO: Add your specialized code here and/or call the base class
    
    	//Eingabebereich auf der rechten Seite um die Button breite verringern
    	CRect editRect;
    	GetRect( &editRect );
    	editRect.right -= 28;
    
    	SetRect( &editRect );
    	CRect rc;
    	GetClientRect(&rc);
    
    	m_Button.SetIcon(IDI_Ordner2, 11, 11);
    
    	m_ButtonRect.bottom = rc.bottom + 1;
    	m_ButtonRect.left = rc.right - 25;
    	m_ButtonRect.right = rc.right;
    	m_ButtonRect.top = rc.top - 1;
    
    	// m_Button is of type CXPButton
    	m_Button.Create ("", WS_VISIBLE | WS_TABSTOP | BS_OWNERDRAW,
    			CRect (m_ButtonRect.left, m_ButtonRect.top, m_ButtonRect.right,
    					m_ButtonRect.bottom), this, MyButton); 
    
    	CEdit::PreSubclassWindow();
    }
    
    void CXPFolderEdit::OnMyButton() 
    {
    	// TODO: Add your control notification handler code here
    	//AfxMessageBox("MyButton wurde gedrückt...", MB_OK, 0);
    
    	char strOrdner[_MAX_PATH] = "";
    	BROWSEINFO browseInfo = {0};
    	browseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
    	browseInfo.pszDisplayName = strOrdner;
    	browseInfo.hwndOwner = m_Button.m_hWnd;
    	LPITEMIDLIST ret;
    	ret = SHBrowseForFolder(&browseInfo);
    	if(ret != NULL) 
    	{
    		SHGetPathFromIDList(ret, strOrdner);
    		SetWindowText(strOrdner);
    		CoTaskMemFree(ret);
    	}
    }
    

    das einbinden funkioniert eigentlich ziemlich einfach... man erstellt ein edit feld in der Dialog ansicht... danach erstellt man eine Membervariable als control für CXPFolderEdit... der rest sollte selbsterklärend aus dem Code oben folgen - (in m_Button.SetIcon(IDI_Ordner2, 11, 11) den entsprechenden Iconcode eingeben... Für Buttons gilt eigentlich das gleiche...
    - Membervariable als control für CXPBUTTON anlegen und mit memberv.SetIcon(...) das Icon festlegen... (muss aber nicht)...

    falls jemand fehler oder verbesserungen findet würde ich mich freuen wenn ihr mir bescheid sagt... Bis denni... 😮 bin jetzt glaube tot müde...


Anmelden zum Antworten