May 08, 2024, 03:53:54 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Cursor change with MouseOver

Started by Bruce Peaslee, January 24, 2006, 12:19:07 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Bruce Peaslee

I have a subclassed static control to use as a hyper link. I've made good process: it's underlined, it's blue, and it opens IE when clicked. It also changes to a hand cursor when you mouse over it. My problem is that the cursor flickers as you move it across the control.

MSDN says that SetCursor (the API call) changes the cursor (it does), but unless the "class cursor" is null, it reverts back as soon as the mouse moves again. I am unable to set the class cursor to null for the control.
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

Ionic Wind Support Team

I do remember a way to do that.  But I'll have to think on it.

You can't change the underlying registered STATIC class as it is part of the OS, but you can register your own class with the OS, copying the needed bits from the original, and leave .hCursor as null.

It is a bit .. messy.  Aurora uses this method to create it's own dialog class based on the registered dialog class.  The API function GetClassInfoExA can retrieve the members of the WNDCLASSEX structure.

And in the above when I refer to 'class' I mean the windows OS class and nothing to do with OOP or aurora classes.  Confusing world isn't it ;)

All in all I would think it would be simpler to whip up your own control based on a captionless window.  It is easy to create reusable controls using OOP classes.

Paul.
Ionic Wind Support Team

Bruce Peaslee

"whip up"? It took me all day to whip up the subclassed static controlÂÃ,  ;)

I'll see what I can do about creating my own control. That kind of thing would be very useful in the long run. But go ahead and think on the other just so we'll have it.
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

Zen

There is a syslink control to create hyperlinks but i think it only works on windows XP and only with the visual styles enabled.

Lewis

Bruce Peaslee

CStatic pLabel;
...
SetClassLongA(pLabel->m_hwnd,GCL_HCURSOR,null);

This is done in the InitDialog method of the dialog containing the static control. No more flicker!
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

Parker

The SysLink control only works on XP, but it doesn't need visual styles. But that's why I don't use it, even though I have XP not everyone else does.

That's cool you can set class properties later on in the program.

Ionic Wind Support Team

The problem with using SetClassLong is your changing that property for every static control in your application, not just the singly subclassed one.

Ionic Wind Support Team

Bruce Peaslee

Quote from: Ionic Wizard on January 24, 2006, 08:36:38 PM
The problem with using SetClassLong is your changing that property for every static control in your application, not just the singly subclassed one.


Are you sure? What would be the impact of that? When I test the cursor over other static controls -- both on the dialog and the main window, there is no change, it remains an arrow.
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

Ionic Wind Support Team

Probably because your setting it to NULL.  If you were to set it to the handle of a valid cursor then every static control would show that cursor.

It was just a note of warning ;)  Windows class changes are application wide. 
Ionic Wind Support Team

Bruce Peaslee

Thanks. I'll watch out for trouble.
Bruce Peaslee
"Born too loose."
iTired (There's a nap for that.)
Well, I headed for Las Vegas
Only made it out to Needles

sapero

I've tried with full oop version, but I couldn't receive WM_SETCURSOR (without superclassing)

Simple hyperlink control - does only attach to standard static control by subclassing them and parent window.
See MakeHyperLink() for parameters
// autogenerated GUID: 6C44F9CA-BB0C-4C08-A789-2623C67966C9

struct linkprop {
NMHDR nmdr;       // need for WM_NOTIFY
int wndproc;      // original WindowProc
int hCursorHand;  // hand cursor (active)
int hFont;        // normal font
int hFontHot;     // underlined font, DeleteObject()
int link;         // The color of shortcuts that have not yet been visited
int alink;        // The color for the active link. Changed to vlink if clicked
int vlink;        // The color of shortcuts that have already been visited
int color;        // current link color
int bMouseMoved;  // if mouse down/up without moving: click
string *url;
}


#define HYPERLINK_1 1000

class dlg:dialog
{
declare OnInitDialog(),int;
declare OnClose(),int;
declare OnNotify(int code,int nID,NMHDR *pnmhdr),int;
}

global sub main()
{
dlg d1;
d1.Create(0,0,398,62,0x80CA0880,0,"Hyperlink demo",0); // DS_CENTER: 0x800
d1.AddControl(CTSTATIC,"Standard Static Control",14,4,113,12,0x5000010B,0x0,1);
d1.AddControl(CTSTATIC,"Hyperlink Static Control",56,24,110,14,0x5000090B,0x0,HYPERLINK_1);
d1.DoModal();
return 0;
}

import int GetDlgItem(int hDlg,int nIDDlgItem);
#define NM_CLICK -2

dlg::OnInitDialog(),int
{
MakeHyperLink(
GetDlgItem(m_hwnd, HYPERLINK_1), // handle to static control
0xFF0000, //  link - The color of shortcuts that have not yet been visited
0x0000FF, // alink - The color for the active link
0x800080, // vlink - The color of shortcuts that have already been visited
"http://www.ionicwind.com/"
);
return true;
}

dlg::OnClose(),int
{
CloseDialog(1);
return true;
}

dlg::OnNotify(int code,int nID,NMHDR *pnmhdr),int
{
if (code = NM_CLICK) and (nID = HYPERLINK_1)
{
MessageBox(0, *(linkprop)pnmhdr.*url, "");
}
return true;
}


/////////////////////////////////////
// hyperlink code area

// faked types :)
import int SetTextColor(int hdc, int crColor);
import int GetParent(int hWnd);
import int CallWindowProc alias CallWindowProcA(int lpPrevWndFunc,int hWnd,int Msg,int wParam,int lParam);
import int PtInRect(RECT *lprc, POINT *pt);
import int ClientToScreen(int hWnd, POINT *lpPoint);
import int InvalidateRect(int hWnd, RECT *lpRect, int bErase);
import int SetCursor(int hCursor);
import int GetCapture();
import int SetCapture(int hWnd);
import int ReleaseCapture();
import int LoadCursor alias LoadCursorA(int hInstance, string *lpCursorName);
#define IDC_HAND 32649
import int GetObject alias GetObjectA(int hgdiobj, int cbBuffer, void *lpvObject);
import int GetProp alias GetPropA(int hwnd, string *lpString);
import int RemoveProp alias RemovePropA(int hwnd, string *lpString);
import int SetProp alias SetPropA(int hwnd, string *lpString, void hData);
import int SendMessage alias SendMessageA(int hWnd,int Msg,int wParam,int lParam);
#define WM_DESTROY  2
#define WM_GETFONT 0x31
#define WM_SETFONT 0x30
#define WM_LBUTTONDOWN 0x201
#define WM_LBUTTONUP 0x202
#define WM_CTLCOLORSTATIC 0x138
#define WM_MOUSEMOVE  0x200
#define WM_NOTIFY 0x4E
#define WM_SETCURSOR 0x20
import int CreateFontIndirect alias CreateFontIndirectA(LOGFONT *lplf);
import int SetWindowLong alias SetWindowLongA(int hWnd, int nIndex,int dwNewLong);
import int GetWindowLong alias GetWindowLongA(int hWnd,int nIndex);
#define GWL_ID   -12;
#define GWL_WNDPROC -4;
import int DeleteObject(int hObject);
import int GetWindowRect(int hWnd,RECT *lpRect);


sub MakeHyperLink(int hwndStatic, int link,int alink,int vlink, string *url)
{
linkprop *p = new(linkprop, 1);

p->url = null;
if (url<>null) p->url = _dupstr(*(string)url);

// cursors
p->hCursorHand  = LoadCursor(0, IDC_HAND);

// colors
p->link  = link;
p->alink = alink;
p->vlink = vlink;
p->color = link;

// prepare 'hot' font: get the original font,
// add 'underline' style, and create new font
byte lf[60]; //LOGFONT lf;
p->hFont = SendMessage(hwndStatic, WM_GETFONT,0,0);
// GetObject(*p.hFont, len(LOGFONT), &lf);
// lf.lfUnderline = true;
GetObject(*p.hFont, 60, &lf);
lf[21] = true;
p->hFontHot = CreateFontIndirect(&lf);

// subclass control
SetProp(hwndStatic, "6C44F9CA-BB0C-4C08-A789-2623C67966C9", p);
p->wndproc = SetWindowLong(hwndStatic, GWL_WNDPROC, &MyLinkProc);

// parent subclassed?
int hwndParent = GetParent(hwndStatic);
if 0=GetProp(hwndParent, "6C44F9CA-BB0C-4C08-A789-2623C67966C9")
{
// in case you want to change kink color:
// subclass parent window and handle WM_CTLCOLORSTATIC
SetProp(hwndParent, "6C44F9CA-BB0C-4C08-A789-2623C67966C9",
SetWindowLong(hwndParent, GWL_WNDPROC, &MyLinkParentProc)
);
}
return;
}


/////////////////////////////
// parent window subclass

sub MyLinkParentProc(int hwnd, int uMsg, int wParam, int lParam),int
{
int lpPrevWndFunc = GetProp(hwnd, "6C44F9CA-BB0C-4C08-A789-2623C67966C9");
select uMsg
{
case WM_DESTROY:
SetWindowLong(hwnd, GWL_WNDPROC, lpPrevWndFunc);
RemoveProp(hwnd, "6C44F9CA-BB0C-4C08-A789-2623C67966C9");

case WM_CTLCOLORSTATIC:
int ret = CallWindowProc(lpPrevWndFunc, hwnd, uMsg, wParam, lParam);
// lParam - Handle to the static control
// wParam - handle to control's HDC
linkprop *p = GetProp(lParam, "6C44F9CA-BB0C-4C08-A789-2623C67966C9");
// if it is a link control - change text color, else do default
if (p<>null) SetTextColor(wParam, p->color);
return ret;
}
return CallWindowProc(lpPrevWndFunc, hwnd, uMsg, wParam, lParam);
}


//////////////////////////////////
// hyperlink window subclass

sub MyLinkProc(int hwnd, int uMsg, int wParam, int lParam),int
{
linkprop *p = GetProp(hwnd, "6C44F9CA-BB0C-4C08-A789-2623C67966C9");
int lpPrevWndFunc = *p.wndproc;

select uMsg
{
case WM_DESTROY:
SetWindowLong(hwnd, GWL_WNDPROC, *p.wndproc);
RemoveProp(hwnd, "6C44F9CA-BB0C-4C08-A789-2623C67966C9");
DeleteObject(p->hFontHot);
if(p->url <> null) FreeHeap(p->url);
delete p;


case WM_SETCURSOR: // not received in oop version
::SetCursor(p->hCursorHand);
return true;

case WM_MOUSEMOVE:
p->bMouseMoved = true;

if (GetCapture() <> hwnd)
{
// set red|underline font color
p->color   = p->alink;
SetCapture(hwnd);
SendMessage(hwnd, WM_SETFONT,p->hFontHot,0);
InvalidateRect(hwnd, null,false);
// to do: WM_SETREDRAW,false
}
else
{
// mouse over static?
RECT rc;
POINT pt;
GetWindowRect(hwnd, rc);
pt.x = lParam&0xFFFF; pt.y = lParam>>16;
ClientToScreen(hwnd, pt);

if false = PtInRect(rc, pt)
{
// no, set blue font
p->color   = p->link;
ReleaseCapture();
SendMessage(hwnd, WM_SETFONT,p->hFont,0);
// to do: WM_SETREDRAW,true
InvalidateRect(hwnd, null,false);
}
}
case WM_LBUTTONDOWN:
p->bMouseMoved = false; // reset event

case WM_LBUTTONUP:

if (p->bMouseMoved = false)
{
// click! - send @IDNOTIFY
p->link = p->vlink; // change color 'idle' to 'visited'
p->nmdr.hwndFrom = hwnd;
p->nmdr.idFrom   = GetWindowLong(hwnd, GWL_ID);
p->nmdr.code     = NM_CLICK;
SendMessage(GetParent(hwnd), WM_NOTIFY, 0, p);
}
}
return CallWindowProc(lpPrevWndFunc, hwnd, uMsg, wParam, lParam);
}