win32 htmlayout點擊按鈕創建新窗口,以及按鈕圖片樣式


最近在做一個C++ win32的桌面圖形程序,我不是C++程序員,做這個只是因為最近沒什么java的活。

windows api,之前接觸的時候,還是大學,那時用這個開發打飛機游戲純粹是娛樂。現在基本忘光了。

 

我要實現的最初的需求也很簡單,就是做一個界面,上面有按鈕,點擊按鈕出現新的窗口。界面是htmlayout來做。所以就是看着代碼,邊學邊做,完全摸着石頭過河,這篇文章也沒啥技術含量。

 

第一步,使用htmlayout,創建一個簡單窗口,這在我上一篇文章有詳細記述:http://www.cnblogs.com/rixiang/p/6605416.html

            要說明一點,項目大的框架,例如如何htmlayoout怎樣引入sdk等等在上述鏈接的文章里說明。本篇文章只具體記錄我解決的問題。就是【win32 htmlayout點擊按鈕創建新窗口,以及按鈕圖片樣式】。

 

第二步,點擊按鈕打開另一個新的窗口

      這里我花了些時間摸索win32窗口的原理,其必要的流程是要先注冊窗口ATOM MyRegisterClass(HINSTANCE hInstance),然后調用CreateWindow這一win32 API,之后

ShowWindow(hWnd, nCmdShow); 以及UpdateWindow(hWnd); main函數的話,接下來就是消息循環。

      這里的重點,也就是我之前沒注意到搞錯過的事情,就是創建子窗口的時候,其CreateWindow中父窗口句柄的參數一定要放入父窗口的hWnd。另外就是注冊lpszClassName一定要和創建的lpszClassName一致。

      所以就是,觸發點擊按鈕事件時,在該事件函數里調用創建子窗口的方法,接着進行子窗口注冊、創建、顯示、更新、消息循環的過程。

      在創建子窗口后,通過EnableWindow(hWndPar,FALSE);函數使父窗口暫時失效,在關閉子窗口的時候,再啟用父窗口。

 

第三步,窗口樣式

      我希望達到的樣式是,界面沒有默認的幫助菜單,以及右上角的X關閉。界面上只有按鈕,關閉按鈕也是自己定義。並且按鈕背景圖片是自己定義的。

      實現了第二步的基礎上又用了大概一天時間摸索。最后發現,取消默認的幫助菜單其實是需要在窗口注冊函數里定義:

wcex.lpszMenuName    = NULL;//MAKEINTRESOURCE(IDC_WIN32HTML);

      之后又困惑於自己CSS里定義的按鈕背景圖片為何沒有生效,最后我試着把html加載路徑由相對路徑改為絕對路徑就OK了。

 

      2017年6月27日補充:要達到界面沒有默認的幫助菜單,以及右上角的X關閉的效果,CreateWindow函數的第三個函數需要為:WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP

        hwnd = CreateWindow("66", NULL, WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP,
            CW_USEDEFAULT, 0, 0, 0, hWndPar, NULL, hInst, NULL);

 

 

最后效果:

      點擊上面的按鈕則彈出新窗口,點擊下面的按鈕則直接退出。

 

下面是源代碼,以后擴展下也許會放到github,暫時就直接貼代碼了。作為java程序員,感覺桌面窗口程序開發也是非常常見的需求,以后可以做一個總結,把python、C++等等多種桌面窗口程序demo做個合集,放到github:

Win32Html.cpp,這里定義的是main函數和主窗口:

// Win32Html.cpp : 定義應用程序的入口點
#include "stdafx.h"
#include "Win32Html.h"
#include "New.h"

#include <htmlayout.h>
#include "behaviors/notifications.h"
#include <htmlayout_behavior.hpp>

#pragma comment(lib,"HTMLayout.lib")
#define MAX_LOADSTRING 100

// 全局變量:
HINSTANCE hInst;                                // 當前實例
TCHAR szTitle[MAX_LOADSTRING];                    // 標題欄文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口類名

// 此代碼模塊中包含的函數的前向聲明:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

// 父窗口句柄
HWND hWnd;

#include "New.h"

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;
    HACCEL hAccelTable;

    // 初始化全局字符串
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_WIN32HTML, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 執行應用程序初始化:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32HTML));

    // 主消息循環:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  函數: MyRegisterClass()
//
//  目的: 注冊窗口類。
//  作者: sonne
//  日期: 2017-03-23
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32HTML));
    wcex.hCursor        = NULL;//LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = NULL;//MAKEINTRESOURCE(IDC_WIN32HTML);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON));

    return RegisterClassEx(&wcex);
}

//
//   函數: InitInstance(HINSTANCE, int)
//
//   目的: 保存實例句柄並創建主窗口
//   作者: sonne
//   日期: 2017-03-23
//   注釋:
//
//        在此函數中,我們在全局變量中保存實例句柄並
//        創建和顯示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 將實例句柄存儲在全局變量中

   hWnd = CreateWindow(szWindowClass,  NULL, WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP/*WS_OVERLAPPED*/,
            CW_USEDEFAULT, 0, 1000, 1000, NULL, NULL, hInstance, NULL);
   
   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

void OnButtonClick(HELEMENT button);

struct DOMEventsHandlerType: htmlayout::event_handler
{
      DOMEventsHandlerType(): event_handler(0xFFFFFFFF) {}
      virtual BOOL handle_event (HELEMENT he, BEHAVIOR_EVENT_PARAMS& params ) 
      { 
        switch( params.cmd )
        {
        case BUTTON_CLICK:              OnButtonClick(params.heTarget); break;// click on button
        case BUTTON_PRESS:              break;// mouse down or key down in button
        case BUTTON_STATE_CHANGED:      break;
        case EDIT_VALUE_CHANGING:       break;// before text change
        case EDIT_VALUE_CHANGED:        break;//after text change
        case SELECT_SELECTION_CHANGED:  break;// selection in <select> changed
        case SELECT_STATE_CHANGED:      break;// node in select expanded/collapsed, heTarget is the node
        case POPUP_REQUEST: 
                                        break;// request to show popup just received, 
                                              //     here DOM of popup element can be modifed.
        case POPUP_READY:               break;// popup element has been measured and ready to be shown on screen,
                                              //     here you can use functions like ScrollToView.
        case POPUP_DISMISSED:           break;// popup element is closed,
                                              //     here DOM of popup element can be modifed again - e.g. some items can be removed
                                              //     to free memory.
        case MENU_ITEM_ACTIVE:                // menu item activated by mouse hover or by keyboard
             break;
        case MENU_ITEM_CLICK:                 // menu item click 
             break;


            // "grey" event codes  - notfications from behaviors from this SDK 
        case HYPERLINK_CLICK:           break;// hyperlink click
        case TABLE_HEADER_CLICK:        break;// click on some cell in table header, 
                                              //     target = the cell, 
                                              //     reason = index of the cell (column number, 0..n)
        case TABLE_ROW_CLICK:           break;// click on data row in the table, target is the row
                                              //     target = the row, 
                                              //     reason = index of the row (fixed_rows..n)
        case TABLE_ROW_DBL_CLICK:       break;// mouse dbl click on data row in the table, target is the row
                                              //     target = the row, 
                                              //     reason = index of the row (fixed_rows..n)

        case ELEMENT_COLLAPSED:         break;// element was collapsed, so far only behavior:tabs is sending these two to the panels
        case ELEMENT_EXPANDED:          break;// element was expanded,

        }
        return FALSE; 
      }
 
} DOMEventsHandler;

LRESULT CALLBACK HTMLayoutNotifyHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LPVOID vParam)
{
  // all HTMLayout notification are comming here.
  NMHDR*  phdr = (NMHDR*)lParam;

  switch(phdr->code)
  {
      case HLN_CREATE_CONTROL:    break; //return OnCreateControl((LPNMHL_CREATE_CONTROL) lParam);
      case HLN_CONTROL_CREATED:   break; //return OnControlCreated((LPNMHL_CREATE_CONTROL) lParam);
      case HLN_DESTROY_CONTROL:   break; //return OnDestroyControl((LPNMHL_DESTROY_CONTROL) lParam);
      case HLN_LOAD_DATA:         break;
      case HLN_DATA_LOADED:       break; //return OnDataLoaded((LPNMHL_DATA_LOADED)lParam);
      case HLN_DOCUMENT_COMPLETE: break; //return OnDocumentComplete();
      case HLN_ATTACH_BEHAVIOR:   break;
  }
  return 0;
}

//
//  函數: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 處理主窗口的消息。
//  作者: sonne
//  日期: 2017-03-23
//  WM_COMMAND    - 處理應用程序菜單
//  WM_PAINT    - 繪制主窗口
//  WM_DESTROY    - 發送退出消息並返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    LRESULT lResult;
    BOOL    bHandled;

    // HTMLayout +
    // HTMLayout could be created as separate window 
    // using CreateWindow API.
    // But in this case we are attaching HTMLayout functionality
    // to the existing window delegating windows message handling to 
    // HTMLayoutProcND function.
    lResult = HTMLayoutProcND(hWnd,message,wParam,lParam, &bHandled);
    if(bHandled)
        return lResult;
    
    // 相對路徑
    char* chRelativePath = "htmlayoutDemo.htm";
    WCHAR wsRelativePath[256]; 

    switch (message)  
    {
        case WM_CREATE:  
        {
            // Normally HTMLayout sends its notifications
            // to its parent. 
            // In this particular case we are using callback function to receive and
            // and handle notification. Don't bother the desktop window (parent of this window)
            // by our notfications.
            HTMLayoutSetCallback(hWnd,&HTMLayoutNotifyHandler,0);

            // attach DOM events handler so we will be able to receive DOM events like BUTTON_CLICK, HYPERLINK_CLICK, etc.
            htmlayout::attach_event_handler(hWnd, &DOMEventsHandler);

            memset(wsRelativePath,0,sizeof(wsRelativePath));
            //char* 轉LPCWSTR
            MultiByteToWideChar(CP_ACP, 0, chRelativePath, strlen(chRelativePath)+1, wsRelativePath,
                      sizeof(wsRelativePath)/sizeof(wsRelativePath[0]));

            //使用絕對路徑
            WCHAR wsPath[MAX_PATH];
            GetCurrentDirectoryW(2048,wsPath);
            wcscat(wsPath,L"\\");
            wcscat(wsPath,wsRelativePath);

            HTMLayoutLoadFile(hWnd,wsPath); 

            SetWindowText(hWnd,"身份認證系統");
            SetForegroundWindow( hWnd );

            //窗口初始化
            DWORD dWidth = HTMLayoutGetMinWidth(hWnd);
            DWORD dHeight = HTMLayoutGetMinHeight(hWnd,dWidth);
            int cx = GetSystemMetrics(SM_CXSCREEN);
            int cy = GetSystemMetrics(SM_CYSCREEN);
            SetWindowPos(hWnd,HWND_TOPMOST,cx/2-dWidth/2,cy/2-dHeight/2,dWidth,dHeight,SWP_NOZORDER);
            HRGN hRgn;
            RECT rect;
            GetWindowRect(hWnd,&rect);
            hRgn = CreateRoundRectRgn(0,0,rect.right-rect.left,rect.bottom-rect.top,20,20);
            SetWindowRgn(hWnd,hRgn,TRUE);
        }
        break;  
    case WM_COMMAND:  
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // 分析菜單選擇:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: 在此添加任意繪圖代碼...
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// “關於”框的消息處理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

//************************************
// 作      者:    sonne
// 函  數  名:  OnButtonClick
// 功      能:  按鈕響應事件
// 完  整  名:  OnButtonClick
// 訪  問  權:  public 
// 返回值類型:  VOID
// 方法限定符:     
//************************************
void OnButtonClick(HELEMENT button)
{
    htmlayout::dom::element cBut = button;
    if (!wcscmp(cBut.get_attribute("id"),L"button1"))
    {
         NEW::InitInstance(hInst, 0, hWnd, szWindowClass);
    }
    //關閉按鈕
    if (!wcscmp(cBut.get_attribute("id"),L"button2"))
    {
        PostMessage(hWnd,WM_DESTROY,NULL,NULL);
    }
}

New.h,這里定義的是點擊按鈕彈出的新窗口的一系列方法:

#pragma once

#include <htmlayout.h>
#include "behaviors/notifications.h"
#include <htmlayout_behavior.hpp>

namespace NEW
{
    #define MAX_LOADSTRING 100
    // 全局變量:
    HINSTANCE hInst;                                // 當前實例
    TCHAR szTitle[MAX_LOADSTRING];                    // 標題欄文本
    TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口類名

    // 此代碼模塊中包含的函數的前向聲明:
    ATOM                MyRegisterClass(HINSTANCE hInstance);
    BOOL                InitInstance(HINSTANCE, int);
    LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

    //
    //  函數: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  目的: 處理主窗口的消息。
    //  作者: sonne
    //  日期: 2017-03-27
    //
    //  WM_COMMAND    - 處理應用程序菜單
    //  WM_PAINT    - 繪制主窗口
    //  WM_DESTROY    - 發送退出消息並返回
    //
    //
    LRESULT CALLBACK NewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int wmId, wmEvent;
        PAINTSTRUCT ps;
        HDC hdc;
        LRESULT lResult;
        BOOL    bHandled;
        lResult = HTMLayoutProcND(hWnd,message,wParam,lParam, &bHandled);
        if(bHandled)
             return lResult;
  
        char* path = "newPage.htm";
        WCHAR wsz[256]; 

        switch (message)  
        { 
        case WM_CREATE: 
            memset(wsz,0,sizeof(wsz));
            MultiByteToWideChar(CP_ACP, 0, path, strlen(path)+1, wsz, sizeof(wsz)/sizeof(wsz[0]));
            HTMLayoutLoadFile(hWnd,wsz); //Hello.htm需要放在和exe同一目錄,記得把dll也copy過去  
            break;  
   
        case WM_COMMAND:  
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);
            switch (wmId)
            {
                case IDM_ABOUT:
                   DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                   break;
                case IDM_EXIT:
                   DestroyWindow(hWnd);
                   break;
                default:
                   return DefWindowProc(hWnd, message, wParam, lParam);
            }
            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;
    }

    //
    //  函數: MyRegisterClass()
    //
    //  目的: 注冊窗口類。
    //  作者: sonne
    //  日期: 2017-03-27
    //
    ATOM NewRegisterClass(HINSTANCE hInstance)
    {
        WNDCLASSEX wcex;

        wcex.cbSize = sizeof(WNDCLASSEX);

        wcex.style            = CS_HREDRAW | CS_VREDRAW;
        wcex.lpfnWndProc    = (WNDPROC)NewWndProc;
        wcex.cbClsExtra        = 0;
        wcex.cbWndExtra        = 0;
        wcex.hInstance        = hInstance;
        wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32HTML));
        wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_WIN32HTML);
        wcex.lpszClassName    = "hh";
        wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

        return RegisterClassEx(&wcex);
    }

    //
    //   函數: InitInstance(HINSTANCE, int)
    //
    //   目的: 保存實例句柄並創建主窗口
    //
    //   注釋:
    //
    //        在此函數中,我們在全局變量中保存實例句柄並
    //        創建和顯示主程序窗口。
    //   作者: sonne
    //   日期: 2017-03-27
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow, HWND hWndPar, TCHAR szWindowClass[])
    {
        HWND newHWnd;
        hInst = hInstance; // 將實例句柄存儲在全局變量中
        htmlayout::dom::element root;
        char szCurrPath[MAX_PATH];
        GetCurrentDirectory(MAX_PATH,szCurrPath);

        NewRegisterClass(hInst);

        newHWnd = CreateWindow("hh", NULL, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hWndPar, NULL, hInst, NULL);

        EnableWindow(hWndPar,FALSE);

        if (!newHWnd)
        {
            return FALSE;
        }

        ShowWindow(newHWnd, 5);
        UpdateWindow(newHWnd);

        MSG msg;
        HACCEL hAccelTable;
        hAccelTable = LoadAccelerators(hInst, (LPCTSTR)IDR_ACCELERATOR);
        while (GetMessage(&msg, NULL, 0, 0)) 
        {
            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        Sleep(100);
        EnableWindow(hWndPar,TRUE);
        SetForegroundWindow( hWndPar );
        BringWindowToTop(hWndPar);
        root = htmlayout::dom::element::root_element(hWndPar);
        if (root)
        {
            root.refresh();
        }
        SetCurrentDirectory(szCurrPath);
        return TRUE;
    }

    // “關於”框的消息處理程序。
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        UNREFERENCED_PARAMETER(lParam);
        switch (message)
        {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;

        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
        }
        return (INT_PTR)FALSE;
    }

}

Resource.h:

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Win32Html.rc
//

#define IDS_APP_TITLE            103

#define IDR_MAINFRAME            128
#define IDD_WIN32HTML_DIALOG    102
#define IDD_ABOUTBOX            103
#define IDM_ABOUT                104
#define IDM_EXIT                105
#define IDI_WIN32HTML            107
#define IDI_SMALL                108
#define IDC_WIN32HTML            109
#define IDC_MYICON                2


//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Settings.rc 使用
//
#define IDI_ICON                        101
#define IDR_ACCELERATOR                 102
#define IDD_MASK                        103
#define IDC_X                           1002


#ifndef IDC_STATIC
#define IDC_STATIC                -1
#endif
// 新對象的下一組默認值
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NO_MFC                    130
#define _APS_NEXT_RESOURCE_VALUE    129
#define _APS_NEXT_COMMAND_VALUE        32771
#define _APS_NEXT_CONTROL_VALUE        1000
#define _APS_NEXT_SYMED_VALUE        110
#endif
#endif

 

htmlayoutDemo.htm:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
      <head>
            <style type="text/css">
                    body { 
                          font:12px Helvetica,Georgia,Arial,sans-serif; 
                          margin:0; 
                          padding:0;
                          background:#fff;
                    }
                    ul{  
                          list-style-type: none;  
                          margin:0px;  
                    }  
                    .bStyle1 {
                           background:url(test_button1.png) top left no-repeat; 
                           width:180px; 
                           height:130px; 
                           border:none; 
                           cursor:pointer;
                    }
                    .bStyle2 {
                           background:url(test_button2.png) top left no-repeat; 
                           width:180px; 
                           height:130px; 
                           border:none; 
                           cursor:pointer;
                    }
            </style>
            <title>
                    new page
            </title>
      </head>
      <body>  
            <h2>htmlayout demo.</h2>  
            <ul>
                <li><input type="button" id="button1" class="bStyle1"/></li>
                <li><input type="button" id="button2" class="bStyle2"/></li>
            </ul>
       </body>  
</html>

 

項目結構:

 

github代碼地址:

https://github.com/SonnAdolf/sonne_desktop_graphical_development

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM