|
I need source code for Buddy Button ,is there anybody have the source code?
|
|
|
|
|
Yes, I have ... send me an email at xxxxxxxxxxxxxxx@yahoo.com and I'll send you the source code ...
modified 29-May-15 19:39pm.
|
|
|
|
|
Is there a way to make the icon scroll when the user scrolls the multiline edit box.
ie: So we can have line numbers etc scroll ?
|
|
|
|
|
|
There's a problem with this control when the user clicks on the icon. The click goes straight through to the edit and is interpreted as a click in the edit. The edit then gets horribly confused and starts overwriting any existing text in the control because it thinks the insertion point has changed.
To fix this, we need to block mouse messages, with something like this:
<br />
<br />
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);<br />
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);<br />
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);<br />
afx_msg void OnRButtonUp(UINT nFlags, CPoint point); <br />
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);<br />
afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);<br />
<br />
<br />
ON_WM_LBUTTONDOWN()<br />
ON_WM_LBUTTONUP()<br />
ON_WM_RBUTTONDOWN()<br />
ON_WM_RBUTTONUP()<br />
ON_WM_LBUTTONDBLCLK()<br />
ON_WM_RBUTTONDBLCLK()<br />
<br />
void CIconEdit::OnLButtonDown(UINT nFlags, CPoint point)<br />
{<br />
if (!IsClickInIcon(point))<br />
{<br />
CEdit::OnLButtonDown(nFlags, point);<br />
}<br />
}<br />
<br />
void CIconEdit::OnRButtonDown(UINT nFlags, CPoint point)<br />
{<br />
if (!IsClickInIcon(point))<br />
{<br />
CEdit::OnRButtonDown(nFlags, point);<br />
}<br />
}<br />
<br />
void CIconEdit::OnRButtonUp(UINT nFlags, CPoint point)<br />
{<br />
if (!IsClickInIcon(point))<br />
{<br />
CEdit::OnRButtonUp(nFlags, point);<br />
}<br />
}<br />
<br />
void CIconEdit::OnLButtonUp(UINT nFlags, CPoint point)<br />
{<br />
if (!IsClickInIcon(point))<br />
{<br />
CEdit::OnLButtonUp(nFlags, point);<br />
}<br />
}<br />
<br />
void CIconEdit::OnLButtonDblClk(UINT nFlags,CPoint point)<br />
{<br />
if (!IsClickInIcon(point))<br />
{<br />
CEdit::OnLButtonDblClk(nFlags, point);<br />
}<br />
}<br />
<br />
void CIconEdit::OnRButtonDblClk(UINT nFlags,CPoint point)<br />
{<br />
if (!IsClickInIcon(point))<br />
{<br />
CEdit::OnRButtonDblClk(nFlags, point);<br />
}<br />
}<br />
<br />
<br />
BOOL CIconEdit::IsClickInIcon(IN CPoint point)<br />
{<br />
BOOL bIsInIcon = FALSE;<br />
<br />
if (m_icon.m_hWnd)<br />
{<br />
CRect rectIcon;<br />
<br />
m_icon.GetWindowRect(&rectIcon);<br />
ScreenToClient(&rectIcon);<br />
<br />
bIsInIcon = rectIcon.PtInRect(point);<br />
}<br />
<br />
return bIsInIcon;<br />
}<br />
Now this is a bit unsatisfactory, and for me it pretty much tips the scales in favour of the GipsySoft solution mentioned in an earlier post. I've actually used it in my application for inserting a "buddy button" in an edit and it works fine. However, it's really a code for a "buddy window" of any type. It would also solve my icon-in-a-password-edit problem.
I'll try to knock together a control with it if I have time.
|
|
|
|
|
OK, folks, first I need to apologise because I think the bug I saw was caused by something else. What happened was that repainting in my edit control stopped working properly. All my fix did was stop the insertion point from changing when the icon is clicked, which you may (or may not) feel is a worthwhile modification. The bug itself remains unexplained. It's happened to other users of my app before, but in my case it vanished after I restarted Windows (but not the application). I don't have any good theories and I haven't found any references to the problem, so for now I'm going to ignore it. Incidentally, the problem still occurs if I change the CIconEdits to normal CEdits, so CIconEdit is innocent in this respect.
Nevertheless, all this spurred me to try another approach to the icon-in-edit problem, using the buddy button code from GipsySoft. At least this has the merit of being usable in password edit controls. Here's the code. It's Johan's code, but with a few modifications and bits stripped out. The end result is quite a bit simpler than the original CIconEdit. It uses the GipsySoft EnableBuddyButton function from http://www.gipsysoft.com/articles/BuddyButton/[^], which I haven't included. It's just a question of dropping in the header file.
There's not much to comment on. First, I found that, in the same function, I needed to do a quick calculation to centre the icon vertically. Second, the icon must be created as a child of the edit's parent in order for the buddy button code to work in unaltered form. Otherwise you need to fiddle with the latter, which I didn't want to do.
My modifications are marked with "DP" throughout.
I hope somebody finds this useful!
Header:
<br />
class CIconWnd : public CStatic<br />
{<br />
public:<br />
CIconWnd();<br />
virtual ~CIconWnd();<br />
<br />
public:<br />
void SetIcon( HICON icon );<br />
<br />
protected:<br />
afx_msg void OnPaint();<br />
afx_msg BOOL OnEraseBkgnd(CDC* pDC);<br />
DECLARE_MESSAGE_MAP()<br />
<br />
private:<br />
HICON m_icon;<br />
};<br />
<br />
<br />
class CIconEdit : public CEdit<br />
{<br />
public:<br />
CIconEdit();<br />
virtual ~CIconEdit();<br />
<br />
public:<br />
void SetIcon(HICON icon);<br />
void SetIcon(UINT iconres);<br />
<br />
protected:<br />
<br />
DECLARE_MESSAGE_MAP()<br />
<br />
private:<br />
void CreateIconWindow();<br />
<br />
CIconWnd m_icon;<br />
HICON m_internalIcon;<br />
};<br />
Body:
<br />
CIconEdit::CIconEdit()<br />
<br />
{<br />
<br />
m_internalIcon = NULL;<br />
m_icon.m_hWnd = NULL;<br />
<br />
}<br />
<br />
CIconEdit::~CIconEdit()<br />
<br />
{<br />
<br />
if( m_internalIcon )<br />
::DestroyIcon( m_internalIcon );<br />
<br />
}<br />
<br />
BEGIN_MESSAGE_MAP(CIconEdit, CEdit)<br />
END_MESSAGE_MAP()<br />
<br />
<br />
<br />
void CIconEdit::SetIcon( HICON icon ) <br />
<br />
{<br />
CreateIconWindow();<br />
<br />
m_icon.SetIcon( icon );<br />
<br />
}<br />
<br />
void CIconEdit::SetIcon( UINT iconres ) <br />
<br />
{<br />
CreateIconWindow();<br />
<br />
if( m_internalIcon )<br />
::DestroyIcon( m_internalIcon );<br />
<br />
m_internalIcon = ( HICON ) ::LoadImage( AfxGetResourceHandle(),<br />
MAKEINTRESOURCE( iconres ),<br />
IMAGE_ICON,<br />
16,<br />
16,<br />
LR_DEFAULTCOLOR );<br />
<br />
ASSERT( m_internalIcon != NULL );<br />
<br />
m_icon.SetIcon( m_internalIcon );<br />
<br />
}<br />
<br />
void CIconEdit::CreateIconWindow()<br />
{<br />
if( !m_icon.m_hWnd )<br />
{<br />
CRect rectWindow;<br />
GetWindowRect(&rectWindow);<br />
<br />
CRect iconRect( 0, 0, GetSystemMetrics( SM_CXSMICON ), rectWindow.Height() );<br />
if(m_icon.m_hWnd==NULL)<br />
m_icon.Create(_T(""), WS_CHILD | WS_VISIBLE, iconRect, GetParent(), 1 );<br />
<br />
if (m_icon.m_hWnd)<br />
{<br />
EnableBuddyButton(GetSafeHwnd(), m_icon.m_hWnd, BBS_LEFT);<br />
}<br />
}<br />
}<br />
<br />
<br />
<br />
<br />
<br />
CIconWnd::CIconWnd()<br />
<br />
{<br />
<br />
m_icon = NULL;<br />
<br />
}<br />
<br />
CIconWnd::~CIconWnd()<br />
<br />
{<br />
}<br />
<br />
BEGIN_MESSAGE_MAP(CIconWnd, CStatic)<br />
ON_WM_PAINT()<br />
ON_WM_ERASEBKGND()<br />
<br />
END_MESSAGE_MAP()<br />
<br />
<br />
void CIconWnd::OnPaint() <br />
<br />
{<br />
<br />
CPaintDC dc( this );<br />
if( m_icon )<br />
{<br />
CRect rect;<br />
GetClientRect( &rect );<br />
<br />
<br />
dc.FillSolidRect( rect, GetSysColor(COLOR_WINDOW) );<br />
<br />
int width = GetSystemMetrics( SM_CXSMICON );<br />
int height = GetSystemMetrics( SM_CYSMICON );<br />
<br />
int nYPos = (rect.Height() - height) / 2;<br />
<br />
::DrawIconEx( dc.m_hDC, 1, nYPos, m_icon, width, height, 0, NULL, DI_NORMAL );<br />
}<br />
}<br />
<br />
BOOL CIconWnd::OnEraseBkgnd( CDC* pDC) <br />
<br />
{<br />
return TRUE;<br />
}<br />
<br />
<br />
void CIconWnd::SetIcon( HICON icon )<br />
<br />
{<br />
m_icon = icon;<br />
if( ::IsWindow( m_hWnd ) )<br />
RedrawWindow();<br />
}<br />
<br />
(Incidentally, I'm sure this has been asked a million times, but is there no way to post properly formatted code, i.e. with tabs/spaces preserved, in these messages? I spent ten or fifteen minutes looking for the answer but couldn't find it.)
|
|
|
|
|
I'll integrate this code in the next update round (which is getting somewht overdue) - with proper attribution but without asking
David Pritchard wrote:
is there no way to post properly formatted code
I use pre-tags (and I notice that there are buttons for them on the formatting toolbar below).
|
|
|
|
|
Heh heh.
Well, actually, I didn't necessarily mean this new version to be definitive, just an alternative, but of course I've no objection to that either . When you mention attribution I assume you're referring to the BuddyButton code, right? I don't think there's any problem there. They let you use it freely. Well, let's put it this way: if there is a problem, we're both equally guilty because I'm using it in my app at work.
On a side note, I was a bit reluctant to use the "API method" employed in the BuddyButton code, rather than a class, but I've come to appreciate its ingenuity. It's incredibly flexible, you can use it anywhere. So it's a method worth studying, I think.
On the pre tags: hey, you learn something every day. I'd never even noticed it. Thanks.
By the way, my password edit-with-icon is working great, finally!
|
|
|
|
|
Rest assured, I will mangle through the code, at least to make it consistent with my efforts. The attributions was actually attributions to you, I won't just lift over code without mentioning your name. As for using other's code, I'm quite prepared to take the blame. We'll see how much de-APIfying I'll have to do, however.
|
|
|
|
|
Can you send me a sample code so I can see how it works?
|
|
|
|
|
|
|
|
In CIconWnd::OnPaint(), you need to make a small modification so that the icon background is painted correctly in Windows 2000. Otherwise, the icon background is always white, even if the window colour is not. This doesn't seem to happen in Windows XP though (don't know about Win9x).
This is the modification.
<br />
dc.FillSolidRect( rect, GetSysColor(COLOR_WINDOW) );<br />
<br />
OK, that's it for now!
|
|
|
|
|
How extremely irritating!
Ah well, this will be incorporated, it's time for an update round of miscellaneous articles - thanks for the notification!
|
|
|
|
|
There's a simple bug in the class: if you use the SetIcon method with the HICON parameter, the icon window is never created. All the create code is inside the other SetIcon method. You need to call this create code from both.
Another thing: why the six-pixel border to the right of the icon? Any particular reason?
Nice control. Cheers.
|
|
|
|
|
David Pritchard wrote:
if you use the SetIcon method with the HICON parameter, the icon window is never created
Time for an update...
David Pritchard wrote:
why the six-pixel border to the right of the icon? Any particular reason?
The text gets a little too close with no border, a 6 pixel margin felt appropriate.
Please note that the icon control was just a way of experimenting with embedded controls - I never expected it to be used as anything but a starting point for embedded buttons etc.
The line-numbering edit (http://www.codeproject.com/editctrl/linenumberedit.asp) is another example of this technique, and the RTF-control with an embedded ruler (http://www.codeproject.com/richedit/rulerricheditctrl.asp)was supposed to be another, more serious, implementation. Although the last one showed a fatal flaw in the concept - the vertical scrollbar...
|
|
|
|
|
Well, anyway, after tweaking the border to make it 1 (I suppose it depends on your icon really - some have borders already), I have it working and it looks very nice.
However, I then tried to use it in a password edit and immediately hit a wall - the password and multiline style are mutually exclusive. Bah! Oh well, you can't have everything.
|
|
|
|
|
As it is update time anyway, I'll make the margin developer-configurable. And I'll check if it is possible to simulate a password edit - hm, intercepting OnChar and pasting... EN_CHANGE... saving the true string internally... Well, security will not exactly be the best, but perhaps enough?
|
|
|
|
|
Well, I'd hadn't really expected you to tackle the password issue, and it may be problematic from the point of view of the user interface, because in XP (with XP styles) password edits show a different character in place of asterisks, and when you press CAPS LOCK a bubble help window appears with a warning... blah blah blah. It's always nice to keep as much of the default implementation as possible to avoid losing changes and improvements that are made later.
Hmm. It's a tricky one. I hesitate to suggest an edit inside an edit... no! no! I've been at this keyboard for too long.
|
|
|
|
|
David Pritchard wrote:
Hmm. It's a tricky one. I hesitate to suggest an edit inside an edit... no! no! I've been at this keyboard for too long.
I imagine that it would be cleaner to host an icon and an edit in a CWnd-derived window instead - just drawing the "edit"-frame around the CWnd instead. OTOH, subclassing in a dialog will not be that simple, and with both solutions, CEDit-specific calls will have to be routed from the host to the child-edit. Methinks that a simple icon/edit-combo does not merit this kind of complication, but on the other hand, we are developers, aren't we
I agree that it should conform to the default implementation - but I still feel that a more basic approach has appeal - if nothing else as an implementation of trapping and modifying edit inputs.
|
|
|
|
|
I don't discount the basic approach, but since I want the icon for purely aesthetic reasons (I put a little key in the edit control and it looked very nice!), I don't want to lose all those nice XP-style-related things.
I haven't looked at any alternative implementations of the icon-in-edit combo, but I did notice comments from people saying that they handled it through non-client painting. Might that be simpler than the CWnd/Edit/icon approach in this case?
|
|
|
|
|
David Pritchard wrote:
I haven't looked at any alternative implementations of the icon-in-edit combo, but I did notice comments from people saying that they handled it through non-client painting. Might that be simpler than the CWnd/Edit/icon approach in this case?
As a matter of fact, I think it is. I made an investigation on what was necessary for a password implementation. Trapping keypresses, pasting, SetWindowText... keep an internal string with the actual contents. Also, copy/cut will have to copy/cut from the internal string instead. Create a dummy password edit and get the default password character.
This is not exactly rocket science, but the big problem is replacing the character. How is the class supposed, when handling WM_SETTEXT, to know if the string is supposed to be added to the internal string or to the control itself? Imagine the case where a user types password characters into the edit... No, the non-client rect would probably be a better choice.
|
|
|
|
|
If I understand you correctly, I'm really beginning to freak out
Some kind of simple pluggable buddies-to-edits framework... I feel the synapses starting to fire up...
|
|
|
|
|
>> and it is too early to destroy and recreate the it.
possibly the edit control could post itself a message in the SetIcon() function and then destroy and recreate itself in the message handler
??
.dan.g.
AbstractSpoon (subscribe)
|
|
|
|
|