• 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

  • 相关阅读:
    2019 牛客多校第二场 H Second Large Rectangle
    2019 牛客多校题解目录
    2019 牛客多校第一场 F Random Point in Triangle
    2019 牛客多校第一场 E ABBA
    2019 牛客多校第一场 D Parity of Tuples
    2019 牛客多校第一场 C Euclidean Distance ?
    2019 牛客多校第一场 B Integration
    2019 牛客多校第一场 A Equivalent Prefixes
    Sigils of Elohim
    UVA 1599 Ideal Path
  • 原文地址:https://www.cnblogs.com/rixiang/p/6626506.html
Copyright © 2020-2023  润新知