 |
|
 |
Great job! You got my 5!
I stumbled upon your code in my search for automatically generating disabled icon. Although you do generate gray image icon, it's too "bright" to look disabled. The transparency of it must be dialed down by half (IMHO) to make it blend in with background somewhat.
I have made couple small adjustments to your CreateGrayscaleIcon function and now it can generate nice disabled icons automatically. I use it for auto-generating toolbar and menu disabled images.
Regards,
Damir
HICON CHyperLink::CreateGrayscaleIcon( HICON hIcon)
{
if (hIcon == NULL)
{
return NULL;
}
HDC hdc = ::GetDC(NULL);
HICON hGrayIcon = NULL;
ICONINFO icInfo = { 0 };
ICONINFO icGrayInfo = { 0 };
LPDWORD lpBits = NULL;
LPBYTE lpBitsPtr = NULL;
SIZE sz;
DWORD c1 = 0;
BITMAPINFO bmpInfo = { 0 };
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if (::GetIconInfo(hIcon, &icInfo))
{
if (GetDIBits(hdc, icInfo.hbmColor, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS) != 0)
{
bmpInfo.bmiHeader.biCompression = BI_RGB;
sz.cx = bmpInfo.bmiHeader.biWidth;
sz.cy = bmpInfo.bmiHeader.biHeight;
c1 = sz.cx * sz.cy;
lpBits = (LPDWORD)GlobalAlloc(GMEM_FIXED, (c1) * 4);
if (lpBits && GetDIBits(hdc, icInfo.hbmColor, 0, sz.cy, lpBits, &bmpInfo, DIB_RGB_COLORS) != 0)
{
lpBitsPtr = (LPBYTE)lpBits;
UINT off = 0;
for (UINT i = 0; i < c1; i++)
{
off = (UINT)( 255 - (( lpBitsPtr[0] + lpBitsPtr[1] + lpBitsPtr[2] ) / 3) );
if (lpBitsPtr[3] != 0 || off != 255)
{
if (off == 0)
{
off = 1;
}
if (lpBitsPtr[3] == 0){
off /= 2;
}else{
lpBitsPtr[3] /= 2;
}
lpBits[i] = m_dwszGrayScalePalette[off] | ( lpBitsPtr[3] << 24 );
}
else{
if (lpBitsPtr[3]!=0){
lpBitsPtr[3] /= 2;
}else{
lpBitsPtr[0] = 128;
lpBitsPtr[1] = 128;
lpBitsPtr[2] = 128;
}
}
lpBitsPtr += 4;
}
icGrayInfo.hbmColor = CreateCompatibleBitmap(hdc, sz.cx, sz.cy);
if (icGrayInfo.hbmColor != NULL)
{
SetDIBits(hdc, icGrayInfo.hbmColor, 0, sz.cy, lpBits, &bmpInfo, DIB_RGB_COLORS);
icGrayInfo.hbmMask = icInfo.hbmMask;
icGrayInfo.fIcon = TRUE;
hGrayIcon = CreateIconIndirect(&icGrayInfo);
::DeleteObject(icGrayInfo.hbmColor);
}
GlobalFree(lpBits);
lpBits = NULL;
}
}
::DeleteObject(icInfo.hbmColor);
::DeleteObject(icInfo.hbmMask);
}
::ReleaseDC(NULL,hdc);
return hGrayIcon;
}
|
|
|
|
 |
|
 |
Hi,
CHyperLink is a nice control but in all it is in conflict with other controls, like XButtonXP. After adding your control to a
dialog with XButtonXP the XButtonXP will be hidden.
Ocrana
|
|
|
|
 |
|
 |
This is a simple but very useful control. My only criticism is that the link text seems to be always left-justified. It would be nice if the text alignment could conform to whatever is set for the control's style (left, centre or right).
One other (minor) niggle is that CHyperLink::OpenUrl() doesn't fail (or even notice) if there's no internet connection available. I changed it to this - which displays a warning dialog if there's no internet connection:-
#include "wininet.h"
int CHyperLink::OpenUrl()
{
if ((m_lpLinkUrl != NULL) && (m_bIsLink) && (_tcslen(m_lpLinkUrl)))
{
if (::InternetCheckConnection(m_lpLinkUrl, FLAG_ICC_FORCE_CONNECTION, 0))
HINSTANCE result = ShellExecute(NULL, _T("open"), m_lpLinkUrl, NULL, NULL, SW_SHOWDEFAULT);
else
{
CWnd* pParent = GetParent();
if (pParent)
::MessageBox(pParent->GetSafeHwnd(), "No internet connection was found ", "Network connection error", (MB_OK | MB_ICONSTOP));
else
::MessageBox(NULL, "No internet connection was found ", "Network connection error", (MB_OK | MB_ICONSTOP));
}
}
else
return -1;
return 0;
}
You then only need to link to wininet.lib. Note that wininet.h should really be in angle brackets but they won't display properly on this site (they get interpreted as a tag).
|
|
|
|
 |
|
 |
An interesting control, for sure...! However, I would like to point out a few things that may be considered bugs.
o The control's mouseover behavior still works when it is not the active application (some apps work like this, some do not).
o The control's correctly acts on the mouse-up, but does not require an initial mouse-down (and mouse capture) to respond to the mouse-up - for example, you can mouse-down on a empty area in the dialog, move the mouse over the control and then release the mouse and the control will incorrectly detect that as a successful click.
o When the mouse is captured on the mouse-down and the control's state changes, the state does not revert back to its "non-pressed" state when the mouse moves off its client area - normal button controls do this so that the user gets a visual indication that the button will NOT activate when they release the mouse button (off of the control's client area).
o Considering the above issue, you get the correct visual behavior if you deactivate the application while keeping the mouse button down, reactivate it and them move the mouse in and out of the control's client area. The behavior seen in that case is how it should work above, even though it is incorrect here.
o When the application is deactivated, the mouse cpature should be released, but I do not think that it is correctly, because as shown above, the control will still change to the "pressed" state after deactivation, where it should not (correct behavior can be verified by doing a mouse-down on a button control, moving the mouse in and out of the button's client area and watching what the button does, and then deactivating/activating and moving the mouse over the button and seeing that its state does not change anymore, and does not react to the mouse-up).
o My number 1 issue with controls designed to accept user input that are based on controls that normally do NOT accept user input - there is no way to focus and activate the control using the keyboard.
Take 'em or leave 'em...!
Peace!
-=- James Please rate this message - let me know if I helped or not!
If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! See DeleteFXPFiles
|
|
|
|
 |
|
 |
Yes, when I firstly made this control I "put it down" just to have it working and I didn't put much attention at how it worked. So also for weird mouse over, mouse out and mouse click behaviors I just passed over. Eventually, with the last update, I could adjust those behaviors, but I'm lazy, so I passed over again. I will probably correct the whole thing with the next update, anyway it would not be difficult to solve those issues by oneself. For the static-based control thing, I must admit that when I firstly wrote this control, I was thinking about the choice between the static or button inheritance and opted for the static one because of "adaptation" to other hyper link controls around. Also, another reason for the static-choice is that a button for me is something that visibly change its state when i click it and if it could be that way for the control in this moment in time, it wasn't in the past with the first release. Probably, with the benefit of hindsight, I picked the wrong one. Then I kept it the same (I mean, static-based) for retro-compatibility.
|
|
|
|
 |
|
 |
When I change the control text,it can't change interface immediately.Should I call the "Invalidate()" function to change the interface?
|
|
|
|
 |
|
|
 |
|
|
 |
|
 |
I'm sorry for your girlfriend. If you mean the source of the control, you can download it through the download link above. If you mean instead the source of the virus I can't help you because I don't release those type of software.
|
|
|
|
 |
|
 |
thank you, dude, I'll try another way to "kill the virus", or send the file to some comercial antivirus. I know that is not your fault. But I don't know why he/she use your code. I'll investigate more about it, or wait for "the antivirus" solution.
DgMv
|
|
|
|
 |
|
 |
multi line url text isnt supported??
say :
"Hello
World"
i tryed so many ways ..can u help pls..i even use this "Hello \nWorld"..but still doesnt work.
??? help
|
|
|
|
 |
|
 |
No, multiline is not supported. I thought it was not so useful. You can solve this problem using a trick, that is splitting the CHyperLink window text for 0x0A (\n) characters and then creating more CHyperLink for each splitted string, increasing the window height as needed. You can do it in the InitDialog or you can create a new place holder control which do this. This is not a real solution because the hover and clicked status will appear in each HyperLink separately, but you can syncronize the mouse events for each HyperLink to accomplish that. I hope this helped.
|
|
|
|
 |
|
 |
following example supports multi-line hyperlink, but i want to use your solution cos of more feature and its easier. So can u please take a look at the following solution and implement the multi-line in ur code as well.. if u get time offcource..
http://www.codeproject.com/miscctrl/XHyperLink.asp
NB: The one you developed has everything just only one functionality missing Multi_Line, please make it full fill.. Thanks
|
|
|
|
 |
|
 |
You don't understand. I've not included the multi-line feature because I didn't think it was important and now I can't implement it not because I would not be able to, but simply because I've not the time to do it. Anyway you could implement it by yourself because it would be very easy to do, just parse for \n chars inside the on paint and repeat the process for each splitted \n terminated line.
|
|
|
|
 |
|
|
 |
|
 |
As you can see I've updated the control and now it supports multiline text.
|
|
|
|
 |
|
 |
Can you please provide a sample project file which shows how you use this class.
|
|
|
|
 |
|
 |
kidding? have a look at download section, up in the article...
|
|
|
|
 |
|
 |
The download section only provides the executable. Not the project file.
|
|
|
|
 |
|
 |
It was simple to use without the project file though.
Cool control! Thanks!
|
|
|
|
 |
|
 |
I was just wondering why you are using TCHAR* and doing your own memory allocation. Why not use CString?
P.S. Interesting article. Keep up the good work.
|
|
|
|
 |
|
 |
Because CString sucks
|
|
|
|
 |
|
 |
Shouldn't the GetLinkText() and GetLinkUrl() return LPCTSTR ? Or, if you prefer, const TCHAR *
e.g.
LPCTSTR GetLinkText();
void SetLinkText(LPCTSTR lpText);
LPCTSTR GetLinkUrl();
void SetLinkUrl(LPCTSTR lpUrl);
BOOL SetFont(LPCTSTR lpFaceName = "Arial", int nSize = 14,
int nWeight = FW_NORMAL, BOOL bItalic = FALSE);
etc.
Remember, const is your friend!
|
|
|
|
 |
|
 |
it's not important if the string you pass as parameter is or not a constant because i locally create a copy of the string passed and so if you modify the string after the call it won't matter to the control.
|
|
|
|
 |
|
 |
K.
Just trying to understand, that's all.
Cheers!
|
|
|
|
 |