2012年7月5日星期四

SysLink.Asm


;半年前发现有个控件能实现超链接(是汇编代码),当时没有保存代码,认为这是雕虫小技,何足挂齿。
;过后,用到超链接的,用按钮的功能实现。
;再过后,感觉有必要使用超链接控件。
;在网上搜索,大多是超类化或者子类话文本控件什么的,好烦。
;今天搜索到了,一定保存。
;后来发现在vs2008的工具栏上也有这个控件。
;在微软的msdn上看,需要先调用一个函数:InitCommonControlsEx。
;可这个函数始终失败!原来还需要设置:
;在汇编中解决的办法是在资源中加入一个xml文件,其内容见附后。
;在vs中是加入如下代码:

;// Enable Visual Style
;#if defined _M_IX86
;#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
;#elif defined _M_IA64
;#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
;#elif defined _M_X64
;#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
;#else
;#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
;#endif
;#pragma endregion

;实现后还要处理一些消息,有点小遗憾。

.386
.model flat,stdcall
option casemap:none
include windows.inc

include kernel32.inc
includelib kernel32.lib

include user32.inc
includelib user32.lib

include comctl32.inc
includelib comctl32.lib 

include shell32.inc
includelib shell32.lib 

include gdi32.inc
includelib gdi32.lib 

.data?
buffer db 512 dup (0) ;最好把报0换成 ?

.code
hInstance dd 0
hWinMain dd 0
szClassName db "made by correy",0
pwndclassex dd 48,3,offset liuchunli,0,0,0,0,0,6,0,offset szClassName,0
stMsg MSG <>
icex INITCOMMONCONTROLSEX <>
hLink dd 0
szSysLink dw "S","y","s","L","i","n","k",0
szhtml db "wellcome to my website:<a href="
       db 34
       db "http://correy.webs.com"
       db 34
       db ">乐观园"
       db "</a>"
       db 13,10 ;不可以"<br>";
       db "If you have any problem, please email me:<a href="
       db 34
       db "mailto:leguanyuan@163.com"
       db 34
       db ">leguanyuan@126.com"
       db "</a>"
       db 13,10
       db 0
hwndFrom dd 0

liuchunli proc uses ebx edi esi,hWnd,uMsg,wParam,lParam
LOCAL hdc:HDC, ps:PAINTSTRUCT
.if uMsg == WM_CLOSE;放置后面会反应更快点。
  invoke DestroyWindow,hWinMain
  invoke PostQuitMessage,0
.elseif uMsg == WM_CREATE
  invoke lstrlen,addr szhtml
  inc eax
  invoke MultiByteToWideChar,CP_ACP, 0,addr szhtml,eax,addr buffer,256
  invoke CreateWindowExW,200h,offset szSysLink,offset buffer, WS_CHILD or WS_VISIBLE or WS_TABSTOP,0,0,610,200,hWnd,9,hInstance,NULL
  mov hLink,eax
.elseif uMsg == WM_NOTIFY
  mov eax,dword ptr [lParam]
  mov eax,[eax+8]

  .if eax == 4 || eax == -2;NM_RETURN == -4  NM_CLICK == -2      
    mov eax,dword ptr [lParam]
    mov eax,[eax]
    mov hwndFrom,eax
    
    mov eax,dword ptr [lParam]
    mov eax,[eax+12+4] ;加一个NMHDR的大小,再加自己的位置。
    
    mov esi,hwndFrom
    mov edi,hLink
    .if esi == edi || eax == 0
      mov eax,dword ptr [lParam]
      add eax,7ch; == 12+16+48*2;MAX_LINKID_TEXT == 48
      invoke ShellExecuteW,hWnd,0,eax,0,0,SW_SHOWDEFAULT
    .endif
    ;还有更多的结构属性,等待自己去发掘。    
  .endif
;.elseif uMsg == WM_PAINT  ;此处的注释不删除,是个小知识点。
  ;invoke BeginPaint,hWnd,addr ps 
  ;mov hdc,eax   
  ;invoke SetTextColor,hdc,0000 ;这个数好像没有用,但没有,又不会显示。原来是上下两句不能少。也即是说,有这个消息,必须加那两行。   
 ;invoke EndPaint,hWnd,addr ps  
.else
  invoke DefWindowProc,hWnd,uMsg,wParam,lParam
  ret;不能去掉。
.endif
xor eax,eax;这两行可以去掉?
ret
liuchunli endp

start: 
mov icex.dwSize , sizeof icex
mov icex.dwICC , ICC_LINK_CLASS
invoke InitCommonControlsEx,addr icex  

invoke GetModuleHandle,0
mov hInstance,eax
mov pwndclassex+20,eax

invoke LoadCursor,0,32512;加载箭头鼠标。
mov pwndclassex+28,eax

;invoke GetStockObject,BLACK_BRUSH
;mov pwndclassex+32,eax

invoke RegisterClassEx,addr pwndclassex
invoke CreateWindowEx,200h,offset szClassName,offset szClassName,0Cf0000h,80000000h,80000000h,710,530,0,0,hInstance,0;0Ca0000h
mov hWinMain,eax

invoke ShowWindow,hWinMain,1;若不想显示,此行也可以去掉。
again:invoke GetMessage,addr stMsg,0,0,0
  cmp eax,0
  je exit
  invoke DispatchMessage,addr stMsg
jmp again
exit:invoke ExitProcess,0
end start
;made at 2011.09.26 

;xml文件的内容如下:根据情况,你可以再修改。
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*' />
    </dependentAssembly>
  </dependency>
</assembly>

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;下面是子类化实现的。
.586
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
include \masm32\include\shell32.inc

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\shell32.lib

UrlProc     PROTO :HWND,:UINT,:WPARAM,:LPARAM

.data?
hInst                       DWORD   ?
hFont                       DWORD   ?
hFontUl                     DWORD   ?
lpOrgStaticProc             DWORD   ?
lpOrgWebProc                DWORD   ?
hBrush                      DWORD   ?
bMouseOver                  DWORD   ?
msg                         MSG     <?>
hEmail                      DWORD   ?
hWeb                        DWORD   ?
hMain                       DWORD   ?

.code
start:
jmp @F
    szWndClsMain                BYTE    "SSC_MAIN", 0
    szWndClsStatic    BYTE "STATIC", 0
    szAppName                   BYTE    "Static Subclass Example", 0
    szEmailText                 BYTE    "Send Gunner Mail", 0
    szEmailURL                  BYTE    "mailto://gunner@gunnerinc.com", 0
    szWebText                   BYTE    "Visit Gunners Webpage", 0
    szWebURL                    BYTE    "http://www.gunnerinc.com", 0
    szShelOpen                  BYTE    "open", 0
    szFontName                  BYTE    "Verdana", 0
@@:
    call    Startup
    
    .while TRUE
     invoke  GetMessage, addr msg, NULL, 0, 0
     .break .if !eax
         invoke TranslateMessage, addr msg
  invoke  DispatchMessage, addr msg
    .endw
 mov  eax, msg.message
 invoke  ExitProcess, eax
    
Startup proc uses ebx 
LOCAL   lfnt:LOGFONT
LOCAL   wc:WNDCLASSEX

    invoke  GetModuleHandle, NULL
    mov     hInst, eax
  
    ;#####  Create 2 fonts
    invoke  RtlZeroMemory, addr lfnt, sizeof LOGFONT

    ;#####  Reg font
    mov     lfnt.lfHeight, -11
    mov     lfnt.lfWeight, FW_NORMAL
    invoke  szCatStr, addr lfnt.lfFaceName, offset szFontName
    invoke  CreateFontIndirect, addr lfnt
    mov     hFont, eax

    ;#####  Bold font
    mov     lfnt.lfUnderline, TRUE
    invoke  CreateFontIndirect, addr lfnt
    mov     hFontUl, eax

    ;#####  Register main window class
    invoke  RtlZeroMemory, addr wc, sizeof WNDCLASSEX

    mov     wc.cbSize, sizeof WNDCLASSEX
    mov     wc.style, CS_HREDRAW or CS_VREDRAW
    mov     wc.lpfnWndProc, offset WndProcMain
    push    hInst
    pop     wc.hInstance
    mov     wc.hbrBackground, COLOR_HIGHLIGHT + 1;  COLOR_3DFACE + 1
    mov     wc.lpszClassName, offset szWndClsMain
    invoke  LoadIcon, NULL, IDI_EXCLAMATION
    mov     wc.hIcon, eax
    mov     wc.hIconSm, eax
    invoke  LoadCursor, NULL, IDC_ARROW
    mov     wc.hCursor, eax
    invoke  RegisterClassEx, addr wc
    
    ;#####  Coords to center window
    invoke  GetSystemMetrics, SM_CXSCREEN
    sub     eax, 300
    shr     eax, 1
    xchg    eax, ebx
    
    invoke  GetSystemMetrics, SM_CYSCREEN
    sub     eax, 123
    shr     eax, 1

    ;#####  Create main window
    invoke  CreateWindowEx,
                WS_EX_APPWINDOW or WS_EX_CONTROLPARENT,
                offset szWndClsMain,
                offset szAppName,
                WS_OVERLAPPED or WS_SYSMENU or WS_MINIMIZEBOX or WS_VISIBLE, 
                ebx, eax,
                300, 123,
                HWND_DESKTOP, NULL,
                hInst, NULL
    mov     hMain, eax
    ret
Startup endp

WndProcMain proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
local   rect:RECT
    mov     eax, uMsg
    .if eax == WM_CREATE
        ;#####  Email Hyperlink
        invoke  CreateWindowEx, 
                    NULL, 
                    offset szWndClsStatic, 
                    offset szEmailText, 
                    WS_CHILD or WS_VISIBLE or SS_NOTIFY, 
                    88, 20, 
                    117, 17, 
                    hWin, 0, 
                    hInst, 0
        mov     hEmail, eax
        
        ;#####  URL is dif than text, save URL
        invoke  SetWindowLong, eax, GWL_USERDATA, offset szEmailURL
        ;#####  Subclass control
        invoke  SetWindowLong, hEmail, GWL_WNDPROC, UrlProc
        mov     lpOrgStaticProc, eax
        
        invoke  SendMessage, hEmail, WM_SETFONT, hFont, FALSE
        
        ;#####  Web Hyperlink
        invoke  CreateWindowEx, 
                    NULL, 
                    offset szWndClsStatic, 
                    offset szWebText, 
                    WS_CHILD or WS_VISIBLE or SS_NOTIFY, 
                    76, 60, 
                    137, 17, 
                    hWin, 0, 
                    hInst, 0
        mov     hWeb, eax
        
        ;#####  URL is dif than text, save URL
        invoke  SetWindowLong, eax, GWL_USERDATA, offset szWebURL
        ;#####  Subclass control
        invoke  SetWindowLong, hWeb, GWL_WNDPROC, offset UrlProc
        mov     lpOrgStaticProc, eax
        
        invoke  SendMessage, hWeb, WM_SETFONT, hFont, FALSE
        
        invoke  GetSysColorBrush,COLOR_HIGHLIGHT ; COLOR_3DFACE
        mov     hBrush, eax

 .elseif eax==WM_CTLCOLORSTATIC
  mov     ecx, hEmail
  mov     edx, hWeb
  .if ecx == lParam || edx == lParam
   .if bMouseOver
    mov  eax, Red   
   .else
       mov     eax, Yellow
   .endif
   invoke  SetTextColor, wParam, eax
   invoke  SetBkMode, wParam, TRANSPARENT
   mov  eax, hBrush
  .endif
  ret
        
    .elseif eax == WM_CLOSE
        invoke  DeleteObject, hFont
        invoke  DeleteObject, hFontUl
        invoke  DeleteObject, hBrush
        invoke  DestroyWindow, hWin
        
    .elseif eax == WM_DESTROY
        invoke  PostQuitMessage, NULL
        
    .else    
        invoke  DefWindowProc, hWin, uMsg, wParam, lParam
        ret
    .endif
    xor     eax, eax
    ret
WndProcMain endp

UrlProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
local   rect:RECT

 mov  eax,uMsg
 .if eax == WM_MOUSEMOVE
     invoke  GetClientRect, hWin, addr rect
  invoke  GetCapture
  ;#####  Make sure the mouse is in our control
  .if eax != hWin
   mov  bMouseOver, TRUE
   invoke  SetCapture, hWin
   invoke  SendMessage, hWin, WM_SETFONT, hFontUl, TRUE
  .endif
  mov  edx,lParam
  movzx eax,dx
  shr  edx,16
  .if eax > rect.right || edx > rect.bottom
      ;#####  moved out of control
   mov  bMouseOver, FALSE
   invoke  ReleaseCapture
   invoke  SendMessage, hWin, WM_SETFONT, hFont, TRUE
  .endif

 .elseif eax == WM_LBUTTONUP
  mov  bMouseOver, FALSE
  invoke  ReleaseCapture
  invoke  SendMessage, hWin, WM_SETFONT, hFont, TRUE
  
  ;#####  Get URL we stored with the control
  invoke  GetWindowLong, hWin, GWL_USERDATA
  invoke  ShellExecute, hMain, offset szShelOpen, eax, NULL, NULL, SW_SHOWNORMAL

 .elseif eax==WM_SETCURSOR
  invoke  LoadCursor, NULL, IDC_HAND
  invoke  SetCursor, eax
  
 .else
  invoke  CallWindowProc, lpOrgStaticProc, hWin, uMsg, wParam, lParam
  ret
 .endif
 xor  eax,eax
 ret
UrlProc endp

end start
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//下面是c/c++代码。
#include <windows.h>
#include <commctrl.h>
#include <tchar.h>

#pragma comment(lib,"comctl32.lib")

#pragma comment( linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"" )

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{
 static TCHAR szAppName[] = TEXT ("Baby Cat") ;
 HWND         hwnd ;
 MSG          msg ;
 WNDCLASS     wndclass ;

 wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
 wndclass.lpfnWndProc   = WndProc ;
 wndclass.cbClsExtra    = 0 ;
 wndclass.cbWndExtra    = 0 ;
 wndclass.hInstance     = hInstance ;
 wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
 wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
 wndclass.lpszMenuName  = NULL ;
 wndclass.lpszClassName = szAppName ;

 INITCOMMONCONTROLSEX icex;
 icex.dwSize = sizeof(icex);
 icex.dwICC = ICC_LINK_CLASS;
 InitCommonControlsEx(&icex);

 if (!RegisterClass (&wndclass))
 {
  MessageBeep(0);
  return 0 ;
 }
 hwnd = CreateWindow (szAppName, // window class name
  TEXT ("Tu Meo"),    // window caption
  WS_OVERLAPPEDWINDOW,        // window style
  CW_USEDEFAULT,              // initial x position
  CW_USEDEFAULT,              // initial y position
  CW_USEDEFAULT,              // initial x size
  CW_USEDEFAULT,              // initial y size
  NULL,                       // parent window handle
  NULL,                       // window menu handle
  hInstance,                  // program instance handle
  NULL) ;                     // creation parameters

 ShowWindow (hwnd, iCmdShow) ;
 UpdateWindow (hwnd) ;

 while (GetMessage (&msg, NULL, 0, 0))
 {
  TranslateMessage (&msg) ;
  DispatchMessage (&msg) ;
 }
 return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 HDC         hdc ;
 PAINTSTRUCT ps ;
 static      RECT  rect ;
 TEXTMETRIC  tm;
 static int cxClient, cyClient , cxChar , cyChar ;
 static TCHAR szBuffer[1024];
 static HWND hLink;

 switch ( message ){ 
  case WM_CREATE:
   hLink = CreateWindow(WC_LINK,TEXT("For more Information <A Href=\"www.google.com\">Click Here</A> or ")\
        TEXT("<A id=\"idInfo\">Here</A>"),WS_CHILD | WS_VISIBLE | WS_TABSTOP,0,0,300,200,hwnd,NULL,GetModuleHandle(0),NULL);
    
   break;
  case WM_SIZE:
   cxClient = LOWORD(lParam);
   cyClient = HIWORD(lParam);
   break;
  case WM_NOTIFY:
   {
    LPNMHDR pp = (LPNMHDR)lParam;
    switch ( pp->code ){
  
     case NM_CLICK:
     case NM_RETURN:
      {
       PNMLINK lp = (PNMLINK)lParam;
       LITEM li = lp->item;

       if ( pp->hwndFrom == hLink && li.iLink == 0 )
        ShellExecute(hwnd,TEXT("Open"),li.szUrl,NULL,NULL,SW_SHOWDEFAULT);
       else if( _tcscmp(li.szID,TEXT("idInfo")) == 0)        
        MessageBox(hwnd,TEXT("Allo"), TEXT("Test"), MB_OK );
      }     
      break;
   
    } 
   }
   break;
   
  case WM_PAINT:
   hdc = BeginPaint(hwnd,&ps);
   EndPaint(hwnd,&ps);
   break;
  case WM_DESTROY:
   PostQuitMessage(0); 
   break;
  default:
   return DefWindowProc (hwnd, message, wParam, lParam) ;
 } 

 return 0;
}

没有评论:

发表评论