• MFC对话框编程详细学习笔记


          因最近研究工作要用到MFC,故再次重温了孙鑫老师的MFC对话框编程,因所用的编译软件为VS2008,与视频中孙老师使用的VC++6.0有很大出入,造成很大不便,我通过各方查找,实现了VS2008相对应于VC++6.0的方法。现将对话框编程整个视频的详细内容分享如下,希望对有缘看到的朋友提供方便。笔者水平有限,难免有不足之处,欢迎批评指正。

    一.准备工作

    1.创建一个MFC Application.

    File->New->Project->Visual C++->MFC->MFC Application.输入项目名称Menu后,点击NEXT,Application type->Single document.建议取消勾选下方的Use Unicode libraries,不然有时候会出错。然后直接点Finish。完成MFC程序创建过程。

    2.新建对话框

          点击Resource View(资源视图)->Dialog,右键添加资源->选择对话框->新建,控件ID为IDD_DIALOG1。

        我们会看到,程序刚建好时资源视图对话框中已有IDD_ABOUTBOX,这个是版本信息提示对话框,程序中点击帮助可查看。

    点击类视图,对话框资源对应的类:CObject->CCmdTarget->CWnd->CDialog

    一个概念:模态对话框和非模态对话框,模态对话框显示时不能执行程序其它任务,而非模态对此无限制。

    3.新建一个和对话框相关的类

    左键资源视图中刚创建的对话框资源,右键右面的对话框,Add Class->Class Name->CTestDlg,MFC中前缀C代表类。

    这样,我们就得到一个新类---CTestDlg,此类就是与刚创建的对话框相对应的,我们对对话框的操作可以在这里进行。

    两个重要函数:

    构造函数:调用基类CDialog的构造函数,IDD为对话框资源的ID

    CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
    
    : CDialog(CTestDlg::IDD, pParent)
    
    { 
    
    }
    
    CTestDlg::DoDataExchange(),此函数主要用来对话框数据交换和数据校验
    
    void CTestDlg::DoDataExchange(CDataExchange* pDX)
    
    {
    
    CDialog::DoDataExchange(pDX);
    
    }
    View Code

    4.创建对话框操作

      在Menu菜单中增加菜单项”Dialog”,属性设置为PopUp

    在该菜单项添加消息响应函数:

    Message Type:COMMAND,Class List:CmenuView

    二.对话框操作

    1.模态对话框与非模态对话框

       (1)模态对话框

    模态对话框的创建函数:CDialog::DoModal()

       模态对话框的关闭函数:CDialog::EndDialog()

    #注意:View类中并不知道CTestDlg类型,要包涵头文件”TestDlg.h”,创建过程在View类的OnDialog()函数中。

    void CmenuView::OnDialog()
    
    {
    
    // TODO: Add your command handler code here
    
    CTestDlg dlg;
    
    dlg.DoModal();//对话框出现就不能在操作其他,除非先关闭它
    
    }
    View Code

    (2)非模态对话框

    非模态对话框的创建函数:BOOL  CDialog::Create(ID号,父窗口指针);

    若父窗口指针设为NULL,对话框父窗口就被设置为主应用程序窗口(此应用中为框架窗口)。

    CtestDlg dlg;

    dlg.Create(IDD_DIALOG1,this);

    #注意:

    对于非模态对话框必须调用ShowWindow();而模态创建函数本身有显示功能  dlg.ShowWindow(SW_SHOW);

    非模态对话框不能是局部变量,而模态因为要暂停,程序停止执行,停留在其生命周期内,所以可以是局部变量

    非模态也可以是局部变量两种方案:

    a.定义Dlg类型的成员变量   

    b.定义指针,在堆上分配内存

    CTestDlg *pDlg=new CTestDlg();

    Dlg->Create(IDD_DIALOG1,this);

    pDlg->ShowWindow(SW_SHOW);

    //这种方法不能解决内存释放重利用问题,最好是添加成员变量,再用析构函数delete释放

    #注意:

    对于模态对话框,点击OK后窗口被销毁,而非模板对话框没被销毁而是隐藏了。

    非模态对话框点击OK时,由基类中OnOK虚函数响应,只隐藏不销毁。

    好的方法是类中要覆盖基类的OnOK()在其内部调用DestroyWindow()销毁。

    所以,之后示例中我们都使用模态对话框。

    2.关于对话框的操作

    (1)Task:在对话框上添加一个按钮,点击该按钮再动态创建一个按钮

    VS2008切换到资源视图,工具栏直接拖动添加名称是Add的按钮。为这个按钮添加消息响应函数,按钮的点击属于通告消息:

    右键按钮选择“Add Event Handler”,MessageType:BN_CLICKED,ClassList:CTestDlg。

    对CTestDlg类添加成员变量  private:  CButton   m_btn;

    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
    // TODO: Add your control notification handler code here
    
    m_btn.Create(“WW”,BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD,
    
                CRect(0,0,100,100),this,123);
    
    )//MSDN中查找Button类型,加了WS_VISIBLE就不用调用ShowWindow了,
    
     //否则必须调用,第三个参数是Button空间矩形区域大小,四是控件父窗口,
    
     //五是ID号
    
    }
    View Code

    #注意:

    我们发现当我们两次点击Add按钮时,非法操作。因为m_btn重复创建窗口,所以错误。

    我们要预防重复创建有两个方法:

    方法一,判断当前button对象如果已经和一个窗口关联在一起了,就销毁窗口,再一次点击再创建。

    增加类CtestDlg成员变量bool m_bIsCreate;这个变量还可以是局部变量,为了不让每次调用都要初始化,把它设置成静态局部变量。

    方法二,凡是从CWnd继承的类都有一个m_hWnd的成员变量,保存了和C++对象相关的句柄。当对象和一个窗口向关联时句柄就有值,否则句柄值为空。

    if(!m_btn.m_hWnd)
    
    {
    
    m_btn.Create(L"WW",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD,
    
    CRect(0,0,100,100),this,123);
    
    }
    
    else
    
    {
    
    m_btn.DestroyWindow();
    
    }
    View Code

    (2)Task:点击静态文本框,让其Caption变为中文

    首先,我们要熟悉相关控件。控件大小对齐等操作使用上面的格式按钮,格式快捷按钮和Format中的菜单项一样,注意Format菜单只有在对话框编辑时才有。

    静态文本框控件:用来标记,起注释作用(放同一个空间,可以点击那个控件按CTRL键拖动),可以在属性页更改Caption。所有的静态文本框ID号都一样。一般不用于响应消息

    编辑框控件:用于输入文本内容。属性页没有Caption

    更改静态文本框ID号为IDC_NUMBER1,增加消息响应函数。

    静态文本框实际上也是窗口,获得窗口内容用函数CWnd::GetWindowText()

    获得指定控件的指针或者子窗口指针函数CWnd::GetDlgItem()。

    void CTestDlg::OnStnClickedNumber1()
    
    {
    
    // TODO: Add your control notification handler code here
    
    CString str;//接收静态文本框文本
    
    If(GetDlgItem(IDC_NUMBER1)->GetWindowText(str),str==”Number1:”)//整个逗号表达式的值是第二个表达式的值
    
    {
    
    GetDlgItem(IDC_NUMBER1)->SetWindowText(“数值1:”);
    
    }
    
    else
    
    {
    
    GetDlgItem(IDC_NUMBER1)->SetWindowText(“Number1:”);
    
    }
    
    }
    View Code

    发现不能实现功能,排错,先看函数调用,没错,再看字符是否写对。我们可以直接复制静态文本框的Caption,这样可以保证正确。排错后发现还是不行。

    答案:静态文本框默认不能接受响应消息,我们必须把属性内的Notify改为TRUE才行。

    (3)Task:在第一个、第二个编辑框分别输入数值,点击Add按钮让第三个显示两者之和

    访问控件方法一:

    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
    int num1,num2,num3;
    
    char ch1[10],ch2[10],ch3[10];
    
     
    
    GetDlgItem(IDC_EDIT1)->GetWindowText((LPTSTR)ch1,10);
    
    GetDlgItem(IDC_EDIT2)->GetWindowText((LPTSTR)ch2,10);
    
    //将字符转换为数值
    
    num1=::atoi(ch1);//ch1字符串中的内容必须是数值
    
    num2=::atoi(ch2);
    
    num3=num1+num2;
    
    ::itoa(num3,ch3,10);
    
    GetDlgItem(IDC_EDIT3)->SetWindowText((LPTSTR)ch3);
    
    }
    View Code

    访问控件方法二:

    GetDlgItemText()相当于GetDlgItem()+GetWindowText()
    
     
    
    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
    int num1,num2,num3;
    
    char ch1[10],ch2[10],ch3[10];
    
    GetDlgItemText(IDC_EDIT1,(LPTSTR)ch1,10);
    
    GetDlgItemText(IDC_EDIT2,(LPTSTR)ch2,10);
    
    num1=::atoi(ch1);//ch1字符串中的内容必须是数值
    
    num2=::atoi(ch2);
    
    num3=num1+num2;
    
    ::itoa(num3,ch3,10);
    
    SetDlgItemText(IDC_EDIT3,(LPTSTR)ch3);
    
    }
    View Code

    访问控件方法三:

    CWnd::GetDlgItemInt()获取一个控件的文本转换为整型返回

    CWnd::GetDlgItemInt(Int nID,BOOL* lpTrans=NULL,BOOL bSigned=TRUE);

    参数一控件ID,参数二错误标示,参数三符号标示,若为真,要看正负号

    CWnd::SetDlgItemInt(Int nID,UINT nValue,BOOL bSigned=TRUE);

    参数一控件ID,参数二欲设置的值,参数三符号标示,若为真,要看正负号

    这种方法推荐采用。

    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
    int num1,num2,num3;
    
    num1=GetDlgItemInt(IDC_EDIT1);
    
    num2=GetDlgItemInt(IDC_EDIT2);
    
     
    
    num3=num1+num2;
    
    SetDlgItemInt(IDC_EDIT3,num3);
    
    }
    View Code

    访问控件方法四(最简单的一种):添加数据变量

    将对话框上的三个编辑框控件分别关联三个成员变量,我们可用成员变量操纵编辑框变量。

    给控件添加成员变量方法:右键控件->Add variable,我们还可以为值设定数值范围,超过的报错提示系统已编写好。添加控件如下图:

    添加后,在CTestDlg::DoDataExchange()(数据交换函数,此函数不能直接调用,必须调用UpdataData())会有如下函数:

    DDX_Text(pDX, IDC_EDIT1, m_num1);

    DDX_Text()用来将制定控件与成员变量相关联

    进行控件与变量的数据交换是DoDataExchange()进行的,但是我们不能直接调用此函数,而是通过调用UpdateData()来实现,参数TRUE表明从控件当中取回值,反之,将成员变量的值赋予控件;为了从编辑框中获得输入值。

    将m_num3的值放入编辑框中再次调用UpdateData(),进行初始化。

    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
        UpdateData();
    
     m_num3=m_num1+m_num2;
    
     UpdateData(false);
    
    }
    View Code

    访问控件方法五:添加控件变量

    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
       int num1,num2,num3;
    
    char ch1[10],ch2[10],ch3[10];
    
    m_edit1.GetWindowText((LPTSTR)ch1,10);
    
    m_edit2.GetWindowText((LPTSTR)ch2,10);
    
    num1=::atoi(ch1);//ch1字符串中的内容必须是数值
    
    num2=::atoi(ch2);
    
    num3=num1+num2;
    
    ::itoa(num3,ch3,10);
    
    m_edit3.SetWindowText((LPTSTR)ch3);
    
    }
    
    //添加控件变量过程和添加数值变量基本一致,把图2category改为control即可。
    View Code

    方法六:通过消息机制获取文本WM_GETTEXT

    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
       int num1,num2,num3;
    
    char ch1[10],ch2[10],ch3[10];
    
        
    
    //发送消息的四种û¡式
    
     
    
    //形式.表明调用的是Win32API函数,而不是类的成员函数
    
        //参数一先获取编辑框指针再指向其句柄,参数二消息类型WM_GETTEXT,
    
    //参数三指示要拷贝的字符数,参数四表示文本buffer。
    
    ::SendMessage(GetDlgItem(IDC->EDIT1)->w_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
    
    //形式.因编辑框已关联控件变量故可直接使用控件变量
    
    ::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
    
     
    
    //形式.不使用Win32API函数,用CWnd成员函数SendMessage()发送消息
    
    GetDlgItem(IDC_EDIT1)->SendMessage(WM_GETTEXT,10,(LPARAM)ch1);
    
     
    
    //形式.使用控件变量的SendMessage()直接发áê消息
    
    m_edit1.SendMessage(WM_GETTEXT,10,(LPARAM)ch1);
    
    m_edit2.SendMessage(WM_GETTEXT,10,(LPARAM)ch2);
    
    num1=::atoi(ch1);//ch1字符串中的内容必须是数值
    
    num2=::atoi(ch2);
    
    num3=num1+num2;
    
    ::itoa(num3,ch3,10);
    
    m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3);
    
    }
    View Code

    访问控件方法七:直接给一个对话框的子控件发送消息

    CWnd::SendDlgItemMessage()等价于先调用GetDlgMessage()再调用SendMessage()。
    
    void CTestDlg::OnBnClickedBtnAdd()
    
    {
    
    int num1,num2,num3;
    
    char ch1[10],ch2[10],ch3[10];
    
        SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1);
    
       SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1);
    
       num1=::atoi(ch1);//ch1字符串中的内容必须是数值
    
    num2=::atoi(ch2);
    
    num3=num1+num2;
    
    ::itoa(num3,ch3,10);
    
       SendDlgItemMessage(IDC_EDIT3,WM_SETTEXT,0,(LPARAM)ch3);
    
      //获取编辑框鼠标复选部分内容而非整个窗口内容EM_GETSEL,EM_SETSEL
    
      //对于EM_SETSEL消息,当范围是0,-1时,全选对话框内容
    
       SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,3);
    
       //将编辑框3设置为焦点所在
    
    m_edit3.SetFocus();
    
    }
    View Code

    ##对话框控件访问七种方式总结:

    1.GetDlgItem()//获取子控件指针->Get(Set)WindowText()

    2.GetDlgItemText()/SetDlgItemText()

    3.GetDlgItemInt()/SetDlgItemInt()

    4.将控件和整型变量相关联

    5.将控件和控件变量相关联

    6.SendMessage()

    7.SendDlgItemMessage()

    其中1和4最常用,当然要根据实际需求

    用的最少的是发送消息6和7,SDK经常用发送消息

    (3)Task:对话框的收缩与扩展功能,点击Shrink按钮的时候切除对话框一部分,之后,将文本内容变为Extend,点Extend时还原对话框

    增加Button控件,编辑相应的消息相应函数。对按钮的相应函数,只需在资源列表双击按钮图标!

    void CTestDlg::OnBnClickedButton2()
    
    {
    
    // TODO: Add your control notification handler code here
    
    CString str;
    
    if(GetDlgItemText(IDC_BUTTON2,str),str==”Shrink<<”)
    
    {
    
    SetDlgItemText(IDC_BUTTON2,”Extend>>”);
    
    }
    
    else
    
    {
    
    SetDlgItemText(IDC_BUTTON2,”Shrink<<”);
    
    }
    
    }
    View Code

    (4)Task:点击Shirk,分隔符以下的收缩,点击Extend恢复。

    增加分隔符用于表示要切割的部分:

    资源视图,分隔符用图像控件代替,查看属性:分隔符ID为IDC_STATIC,说明不能接受相应消息。改为IDC_SEPARATOR,SunKen属性改为TRUE。

    思路:对话框尺寸、原点应保留。右下角横坐标不变,纵坐标改变

    static  CRect  rectLarge;//为避免重复定义,声明为static
    
    static  CRect  rectSmall;
    
    //判断对话框原始尺寸是否是没被赋值,用CRect成员函数
    
    //IsRectNull()看CRect四个坐标值是否都为空,IsRectEmpty()看CRect区域是否为空
    
    if(rectLarge.IsRectNull())
    
    {
    
    CRect  rectSeparator;
    
    //获取原始窗口矩形区域尺寸
    
    GetWindowRect(&rectLarge);
    
    //获取切割后剩余矩形区域尺寸大小,左上角顶部左顶点不变,变化的只是右下角顶点的纵坐标  
    
          GetDlgItem(IDC_SEPARATOR)->GetWindowRect(&rectSeparator);
    
    rectSmall.left=rectLarge.left;
    
    rectSmall.top=rectLarge.top;
    
    rectSmall.right=rectLarge.right;
    
    rectSmall.bottom=rectSeparator.bottom;
    
    }
    
    //伸缩扩展功能CWnd::SetWindowPos()设置顶窗口位置与ZOrder
    //SetWindowPos(const CWnd* pWndInsertAfter,int x,int y,int cx,int cy,UINT nFlags);详见MSDN
    
    if(str==L"Shrink<<")
    
    {
    
    SetWindowPos(NULL,0,0,rectSmall.Width(),rectSmall.Height(),
    
     SWP_NOMOVE|SWP_NOZORDER);
    
    }
    
    else
    
    {
    
    SetWindowPos(NULL,0,0,rectLarge.Width(),rectLarge.Height(),
    
     SWP_NOMOVE|SWP_NOZORDER);
    
    }
    
    //隐藏分割线将控件的visible属性设为FALSE
    View Code

    (5)Task:编辑框1输入点击回车,鼠标焦点转向下一个控件

    #发现一旦回车,对话框消失,因为OK键默认相应回车

    a.将OK键的相应函数取消。双击资源视图OK键进入响应函数,注释其调用的OnOK();

    b.SetWindowLong(HWND hWnd,int nIndex,LONG dwNewLong);改变指定窗口的属性。参数1指定窗口,参数2指定改变类型,参数3指定新值

    c.VC++6.0在CTestDlg类中添加WM_INITDIALOG消息,此消息是指在对话框都创建好且显示前要发送的消息。VS2008在CTestDlg类中右键属性窗口中的重写图标(最后一个)添加OnInitDialog消息映射。

    此过程不能在对话框的ONCREATE函数中设置,因为我们是对编辑框的操作,在对话框ONCREATE函数中,编辑框还没有产生。子控件创建过程在对话框的ONCREATE函数执行后和对话框显示之前完成。

    WNDPROC  prevProc;
    //定义一个窗口过程类型,放在最前面
    BOOL CTestDlg::OnInitDialog()
    {
    
    CDialog::OnInitDialog();
    // TODO:  Add extra initialization here
    prevProc=(WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd,GWL_WNDPROC,(LONG)WinWuProc);
    
    return TRUE;  // return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
    
    }
    
     
    
    //写窗口过程函数:
    LRESULT CALLBACK WinWuProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    {
    
    //对于一个WM_CHAR消息,w_Param保存了字符的ASCII码
    //如果消息是WM_CHAR并且是回车,让光标移到下一个编辑框窗口
    if(uMsg==WM_CHAR&&wParam==0x0d)
    {
    
    //目前窗口过程函数是全局函数,所以不能用CWnd成员函数,只能用WIN32API函数(SDK平台函数)
    
    //获取编辑框下一个窗口句柄GetNextWindow()
    
    //::SetFocus(::GetNextWindow(hwnd,GW_HWNDNEXT));
    
    //另一个获取窗口句柄函数
    
    ::SetFocus(::GetWindow(hwnd,GW_HWNDNEXT));
    
    //第三种获取窗口句柄函数
    
    ::SetFocus(::GetNextDlgTabItem(::GetParent(hwnd),hwnd,false));
    
    return 1;
    
    }
    else//如果不是,返回给先前窗口过程函数
    {
    
    return prevProc(hwnd,uMsg,wParam,lParam);
    
    }
    }
    
    //注意将编辑框一属性MultiLine设为True;
    View Code

    Task(5)方法二(更方便)实现按回车,焦点依次下移

    缺省按钮的响应函数来响应回车键,在相应函数中将焦点依次向下传递

    将编辑框1的multiLine属性恢复为FALSE。

    在OnOk()VS2008变为OnBnClickedOk()函数中完成

    void CTestDlg::OnBnClickedOk()
    
    {
    
    // TODO: Add your control notification handler code here
    
    //GetDlgItem(IDC_EDIT1)->GetNextWindow()->SetFocus();只能到第二个
    
    //GetFocus()->GetNextWindow()->SetFocus();//可实现但是最后一个会出错
    
    //GetFocus()->GetNextWindow(GW_HWNDNEXT)->SetFocus();//可实现但是最后一个会出错
    
    //GetNextDlgTabItem()此函数按照Tab_Stop属性依次向下查找
    
    //查看Tab Order,Format子菜单下Tab Order
    
    GetNextDlgTabItem(GetFocus())->SetFocus();
    
    //OnOK();
    
    }
    View Code

    #注意:

    我们可以把Shrink<<按钮设置为Default Button,这是回车时,由Shrink<<按钮的相应函数进行相应。一般情况默认OnOk()响应回车,就算没有OK按钮。

    我们可以自己添加OK按钮,ID设置为IDOK而不是IDC_OK。

    Task(6):逃跑按钮

    实现细节:在对话框上增加一个按钮,我们点击按钮时,按钮自动移动到其他位置

    在这里,我们做一个简化,巧妙地方法是设置两个相同的按钮,鼠标移动到其中一个就隐藏。

    #注意:对话框Font属性可修改字体

    实现步骤:

    1.添加两个相同的按钮控件IDC_BUTTON1和IDC_BUTTON2

    2.增加新类:->project->Add Class->MFC类CWinWu,基类设置为CButton.

    3.将两个控件分别关联成员变量m_btn1、m_btn2,variable设置为CWinWu.

    4.在CMFC_Dialog2Dlg头文件中包涵”WinWu.h”

    5.为CWinWu类中添加OnMouseMove()消息处理函数,用这个函数来完成一个控件隐藏一个控件显示的功能。

    6.获取控件指针:添加成员变量m_pBtn,类型CWinWu*

    //m_btn1和m_btn2作为CWinWu的实例化对象内部都有m_pBtn这个指针变量。我们让每一个对象的指针保留对方对象的首地址,当其中一个隐藏,我们就调用它的指针(指向另一个对象)的ShowWindow()。

    7.交换地址放在OnInitDialog()函数内部,此函数用来响应WM_INITDIALOG消息的,该消息在对话框显示之前发送。

    BOOL CMFC_Dialog2Dlg::OnInitDialog()
    
    {
    
    CDialog::OnInitDialog();
    
    m_btn1.m_pBtn=&m_btn2;
    
    m_btn2.m_pBtn=&m_btn1;
    
    return TRUE;  // return TRUE  unless you set the focus to a control
    
    }
    View Code

    8.隐藏自身按钮

    void CWinWu::OnMouseMove(UINT nFlags, CPoint point)
    
    {
    
    // TODO: Add your message handler code here and/or call default
    
    ShowWindow(SW_HIDE);
    
    m_pBtn->ShowWindow(SM_SHOW);
    
    CButton::OnMouseMove(nFlags, point);
    
    }
    View Code

    9.隐藏其中的一个按钮:到资源视图,选中其中一个属性visible->false
    ---------------------
    版权声明:本文为CSDN博主「Bright_Geek」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/bright_geek/article/details/40456279

  • 相关阅读:
    时间操作、时间戳
    滚动条大于120px时,判断pc端的情况下,导航条固定定位
    通过js中的useragrent来判断设备是pc端还是移动端,跳转不同的地址
    js构建函数,点击按钮显示div,再点击按钮或其他区域,隐藏div
    localStorage用法总结
    轮播插件、原生js编写,弄懂这个,基本上各种轮播都可以自己写了
    (原)选择远比努力重要
    Java线程之间通信
    迪杰斯特拉(Java)
    FFTW中文参考
  • 原文地址:https://www.cnblogs.com/blogpro/p/11340233.html
Copyright © 2020-2023  润新知