News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How to create a hyperlink?

Started by Stas_Rocketman, April 15, 2012, 02:13:00 PM

Previous topic - Next topic

Stas_Rocketman

Hello guys... I want to make a simple app with a hyperlink and a button in its window.
Can anybody tell me, how to create a hyperlink in this application?

Here is a code of that program


.486                                      ; create 32 bit code
.model flat, stdcall                      ; 32 bit memory model
option casemap :none                      ; case sensitive

;     include files
;     ~~~~~~~~~~~~~
include \masm32\include\windows.inc       ; main windows include file
include \masm32\include\masm32.inc        ; masm32 library include

; -------------------------
; Windows API include files
; -------------------------
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
include \masm32\include\ole32.inc
include \masm32\include\msvcrt.inc

;     libraries
;     ~~~~~~~~~
includelib \masm32\lib\masm32.lib         ; masm32 static library

; ------------------------------------------
; import libraries for Windows API functions
; ------------------------------------------
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\msvcrt.lib

;__________________________________________________________________________________________

.const
hWnd1_Width = 256
hWnd1_Height = 179
hWnd1_button1_ID = 1
hWnd1_button1_Width = 75
hWnd1_button1_Height = 25
hWnd1_button1_X = hWnd1_Width-hWnd1_button1_Width - 16
hWnd1_button1_Y = hWnd1_Height-hWnd1_button1_Height - 32
.data?
hWnd1_Button1 HWND ?
hFontN HWND ?
hInstance HINSTANCE ?
.data
Textbutton1 db "Exit",0
TextHypLink1 db "www.masm32.com",0
FontName db "MS Sans Serif",0
lf LOGFONT <>
;_____________________________________________
BtnClName db "button",0
StarClName db "static",0
AppName db "Application 1",0
;_____________________________________________
sz_string_1 db "Couldn't register window class!", 0
sz_string_2 db "Couldn't create window!", 0
sz_string_3 db "Couldn't create button!", 0
;__________________________________________________________________________________________

.code

start:

Main proc
LOCAL msg :MSG
LOCAL hWnd :HWND
LOCAL wc :WNDCLASSEX
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_BYTEALIGNCLIENT
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
invoke GetModuleHandle, NULL
mov hInstance, eax
mov wc.hInstance, eax
mov wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszClassName, OFFSET AppName ;ClassName

invoke LoadIcon, hInstance, 500
mov wc.hIcon, eax
mov wc.hIconSm, eax

invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax

; Registering window class
invoke RegisterClassEx, addr wc
test eax, eax
jnz @F
invoke MessageBox, hWnd, \
addr sz_string_1, \
NULL, \
MB_OK or MB_ICONERROR
xor eax, eax
jmp @L_exit

@@:
; Centering window
invoke GetSystemMetrics, SM_CXSCREEN
sub eax, hWnd1_Width
shr eax, 1
mov ebx, eax
invoke GetSystemMetrics, SM_CYSCREEN
sub eax, hWnd1_Height
shr eax, 1

; Создаём окно
invoke CreateWindowEx, 0,\
ADDR AppName, \;ClassName,\
ADDR AppName,\
WS_SYSMENU,\ ; or WS_DLGFRAME
ebx, eax,\
hWnd1_Width, hWnd1_Height,\
NULL,\
NULL,\
hInstance,\
NULL
test eax, eax
jnz @F
invoke MessageBox, hWnd, \
addr sz_string_2, \
NULL, \
MB_OK or MB_ICONERROR
xor eax, eax
jmp @L_exit
@@:
mov hWnd, eax

; Getting font
invoke GetStockObject, DEFAULT_GUI_FONT

mov lf.lfHeight, -11
mov lf.lfWeight, 500
invoke CreateFontIndirect, addr lf
mov hFontN, eax

invoke CreateWindowEx, 0, \
ADDR BtnClName, \
ADDR Textbutton1, \
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON, \
hWnd1_button1_X, hWnd1_button1_Y, \
hWnd1_button1_Width, hWnd1_button1_Height, \
hWnd, \
hWnd1_button1_ID, \
hInstance, \
NULL
test eax, eax
jnz @F
invoke MessageBox, hWnd, \
addr sz_string_3, \
NULL, \
MB_OK or MB_ICONERROR
xor eax, eax
jmp @L_exit
@@:
mov hWnd1_Button1,eax
invoke SendMessage, hWnd1_Button1, WM_SETFONT, hFontN, 1

invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd
db 5 dup (90h) ; 5 nops
@L1:
invoke GetMessage, addr msg, 0, 0, 0
test eax, eax
jz @L_2
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp @L1
@L_2:
mov eax, msg.wParam
@L_exit:
invoke ExitProcess, eax
Main endp
;__________________________________________________________________________________________


;__________________________________________________________________________________________
align 16
;__________________________________________________________________________________________


;__________________________________________________________________________________________
WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg == WM_COMMAND
mov ecx, lParam
jcxz @L1
mov eax,wParam
.IF ax == BN_CLICKED*65536 + hWnd1_button1_ID
invoke ExitProcess, 0
.ENDIF
@L1:
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
;__________________________________________________________________________________________

end start


And sorry for my bad English  ::) I'm from Russia and I'm just 17


jj2007

First things first: Welcome to the Forum :thumbu

There are two options that come spontaneously to my mind:
1. Use a RichEdit control. It can handle hyperlinks
2. By hand:
    - Create a font that looks like a hyperlink (blue, underlined)
    - TextOut
    - create a region around the text and check in WM_MOUSEMOVE if the cursor is inside the region
    - if yes, change the cursor
    - if a button is pressed, open the link.


dedndave

i guess we could use the pre-defined "syslink" system class   :P

http://msdn.microsoft.com/en-us/library/bb760706%28VS.85%29.aspx

it requires common controls 6 or better, so you'll want a manifest
i may play with it, later

something like this...

IDW_HYPERLINK  EQU 2012

        .DATA

icc            INITCOMMONCONTROLSEX <sizeof INITCOMMONCONTROLSEX,ICC_LINK_CLASS>
szSyslinkClass db 'syslink',0
szHyperlink    db 'For more information, <A HREF=\"http://www.microsoft.com\">click here</A>',0

        .CODE

        INVOKE  InitCommonControlsEx,offset icc
        INVOKE  CreateWindowEx,NULL,offset szSyslinkClass,offset szHyperlink,
                WS_VISIBLE or WS_CHILD or WS_TABSTOP,
                rect.left,rect.top,rect.right,rect.bottom,
                hDlg,IDW_HYPERLINK,hInstance,NULL

Stas_Rocketman

Thanks, dedndave, it works. But that hyperlink just appears in window with blue and underlined font and nothing more. It is not clickable. Ummm... so now there is another problem. How to make that hypellink work? :D Maybe through the WndProcess function... or something else?

dedndave

CreateProcess is one way to go
but, i think ShellExecute is the way to fly, in this case...
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx

ShellExecute(NULL, "open", "http://www.microsoft.com", NULL, NULL, SW_SHOWNORMAL)
you can get the link text from the syslink control (prefered - so it supports more than one syslink)
this will open in the user's default browser - you might use SW_SHOWDEFAULT, instead

as for detecting the click...
the parent window receives a WM_NOTIFY message when the link is clicked
lParam is a pointer to a NMHDR structure
the NMHDR.hwndFrom member will have a handle to the syslink control
the NMHDR.idFrom member will have the syslink control ID
the NMHDR.code member will be NM_CLICK

http://msdn.microsoft.com/en-us/library/bb760714%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb775583%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/bb775514%28v=vs.85%29.aspx

dedndave

#7
this will give you a starting place
        .DATA

szOpen  dw 'o','p','e','n',0

        .CODE
;
;
;
        LOCAL   sli:LITEM

    .if uMsg==WM_NOTIFY
        mov     edx,lParam
        .if [edx].NMHDR.code==NM_CLICK
            INVOKE  SendMessage,[edx].NMHDR.hwndFrom,LM_GETITEM,NULL,addr sli
            INVOKE  ShellExecuteW,NULL,offset szOpen,addr sli.szUrl,NULL,NULL,SW_SHOWDEFAULT
        .endif
    .elseif......

the string in the LITEM structure is unicode, supposedly
you can use it directly by using ShellExecuteW, or maybe convert it to ansi and use ShellExecute
for the ansi version, szOpen should be...
szOpen  db 'open',0

EDIT - oops, added ".endif"

dedndave

a little better code
i added a test to make sure the message came from the syslink by checking the control ID
        .DATA

szOpen  dw 'o','p','e','n',0

        .CODE
;
;
;
        LOCAL   sli:LITEM

    .if uMsg==WM_NOTIFY
        mov     edx,lParam
        .if [edx].NMHDR.code==NM_CLICK
            .if [edx].NMHDR.idFrom==IDL_SYSLINK1
                INVOKE  SendMessage,[edx].NMHDR.hwndFrom,LM_GETITEM,NULL,addr sli
                INVOKE  ShellExecuteW,NULL,offset szOpen,addr sli.szUrl,NULL,NULL,SW_SHOWDEFAULT
            .endif
        .endif
    .elseif......

Stas_Rocketman

Sorry, didn't understood, what does this line of code?
Quote from: dedndave on April 25, 2012, 05:06:26 PM

                INVOKE  SendMessage,[edx].NMHDR.hwndFrom,LM_GETITEM,NULL,addr sli

Is it extracting URL from the syslink text?
But thanks... I've modified this code a bit, but it also works properly.

.data
syslink1_Text db '<A HREF="">MASM forum</A>',0
syslink1_SiteAddr db 'www.masm32.com/board/index.php', 0
SyslinkClName db 'syslink', 0
...
invoke CreateWindowEx, 0, \
ADDR SyslinkClName, \
ADDR syslink1_Text, \
WS_VISIBLE or WS_CHILD or WS_TABSTOP, \
...
.ELSEIF uMsg == WM_NOTIFY
mov     eax,lParam
.IF [eax].NMHDR.code == NM_CLICK
.IF [eax].NMHDR.idFrom == hWnd1_syslink1_ID
push 0
push 0
push 0
push offset syslink1_SiteAddr
push offset sz_Open
push hWnd
call ShellExecute
.ENDIF
.ENDIF
.ELSEIF

dedndave

yes - it gets the URL from the hyperlink

the method you are using will work fine if you have only one link

but, i was trying to make a more "generic" routine that could be used where you have more than one hyperlink
rather than looking up which link sent the message in some kind of table - just get it from the link, itself

Force

Simple HyperLink

Never Stop Until You Are Better Than The Best

hfheatherfox07

Quote from: Force on May 14, 2012, 08:12:58 PM
Simple HyperLink



Hi there Force ...nice to meet you !
You link leads us to a page were you have Call Listview From Menu
"AniMultipleWindows.zip"   

I noticed that you still have the black corners appearing .... we solved that if you are interested here : http://www.masm32.com/board/index.php?topic=17255.msg144527#msg144527

Download:

http://www.masm32.com/board/index.php?action=dlattach;topic=17255.0;id=9628

just 2 extra lines in the code

dedndave

yah - that's not a great solution to the black corners issue   :P
i got rid of them by moving the CreateWindowEx call from WM_CREATE
but - i have also managed to create child windows without black corners in WM_CREATE
i haven't found the magic style flag that is causing this, yet - lol
it may be WS_CLIPCHILDREN

as for the link to the attachment - i downloaded it fine, here
maybe you have a virus, Heather   :eek

hfheatherfox07

Quote from: dedndave on May 16, 2012, 01:31:08 AM

as for the link to the attachment - i downloaded it fine, here
maybe you have a virus, Heather   :eek

???? what do you mean? I never said it did not download fine