自绘控件

在【2013 duilib入门简明教程 -- 复杂控件介绍 (13)】中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如菜单控件)。虽然duilib没有提供这些控件,但是自己绘制起来也是非常方便的,不过duilib的自绘可比MFC方便得不止一点点了,其实duilib的自绘大都不用自己绘制,就是一些控件和图片的组合而已,相当简单方便~~~

一、菜单控件

其实菜单控件的外观和ListBox非常像,所以我们可以用教程13的ListBox控件模拟,也可以自行用其他的组合,由于duilib自带的Demo里有两个Menu,而且样式还很不错,所以Alberl就拿来用了,不过那几个Demo同样是复杂得要命,还记得教程13中的ListCtrl使用起来多么简单吗?如果不觉得它简单,那么再对比一下duilib自带的ListDemo,就能感觉到它的简单啦~O(∩_∩)O~

相信看过duilib自带的MenuDemo以及ListDemo里面的菜单,都不会觉得菜单很简单吧,那么来看看下面这个菜单的实现吧~O(∩_∩)O~

1、新建一个menu.xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<Window size="120,82">
<VerticalLayout bkimage="file='Menu/menu_bk.png' corner='40,8,8,8'" hole="false"><List header="hidden" inset="8,8,8,8" itemhotimage="file='Menu/menu_hot_bk.png' corner='2,2,2,2'"><ListContainerElement name="menu_Open" height="22" inset="40,0,0,0"><Label text="打开" mouse="false"/></ListContainerElement><ListContainerElement name="menu_Mark" height="22" inset="40,0,0,0"><Label text="标注" mouse="false"/></ListContainerElement><ListContainerElement name="menu_Delete" height="22" inset="40,0,0,0"><Label text="删除" mouse="false"/></ListContainerElement></List>
</VerticalLayout>
</Window>

可以看到Menu其实就是一个List和图片组合的,当然,亲们也可以用教程13中的ListBox来替换上述内容,只不过需要自己调整一下。这里非常感谢提供MenuDemo的大神,菜单样式非常漂亮~O(∩_∩)O~

2、新建一个DuiMenu.h,如下(为了方便演示,将cpp的代码都放到了.h里,并且减少了空行,在最后的教程里,会有一个完整的工程下载):

#pragma once
// 此处需要包含duilib的头文件#include <UIlib.h>那一段,详细代码请见前面教程class CDuiMenu : public WindowImplBase
{
protected:virtual ~CDuiMenu(){};        // 私有化析构函数,这样此对象只能通过new来生成,而不能直接定义变量。就保证了delete this不会出错CDuiString  m_strXMLPath;public:explicit CDuiMenu(LPCTSTR pszXMLPath): m_strXMLPath(pszXMLPath){}virtual LPCTSTR    GetWindowClassName()const{ return _T("CDuiMenu "); }virtual CDuiString GetSkinFolder()          { return _T("");            }virtual CDuiString GetSkinFile()            { return m_strXMLPath;      }virtual void       OnFinalMessage(HWND hWnd){ delete this;              }virtual LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){Close();bHandled = FALSE;return 0;}void Init(HWND hWndParent, POINT ptPos){Create(hWndParent, _T("MenuWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);::ClientToScreen(hWndParent, &ptPos);::SetWindowPos(*this, NULL, ptPos.x, ptPos.y, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);}virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam){LRESULT lRes = 0;BOOL    bHandled = TRUE;switch( uMsg ){case WM_KILLFOCUS:    lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); break; default:bHandled = FALSE;}if(bHandled || m_PaintManager.MessageHandler(uMsg, wParam, lParam, lRes)) {return lRes;}return __super::HandleMessage(uMsg, wParam, lParam);}
};

3、此时一个菜单控件的所有代码就完成啦,下面接下来要显示菜单控件,我们模仿MFC的方式,即点击一个菜单按钮后,弹出菜单项~

显然第一步需要添加一个菜单按钮,XML如下:

<Button name="btnMenu" text="选项" float="true" pos="475,28,0,0" width="37" height="19" align="center" normalimage="" hotimage="Menu/btn_menu_hot.png" pushedimage="Menu/btn_menu_hot.png" focusedimage="Menu/btn_menu_hot.png" textcolor="#FF000000" hottextcolor="#FFFFFFFF" pushedtextcolor="#FFFFFFFF" focusedtextcolor="#FFFFFFFF" bkcolor="#FFECE9D8" />

第二步就是响应菜单按钮的点击,在主窗口的Notify函数里添加以下代码:

if( msg.sType == _T("click") ) {if( msg.pSender->GetName() == _T("btnMenu") ) {POINT pt = {msg.ptMouse.x, msg.ptMouse.y};CDuiMenu *pMenu = new CDuiMenu(_T("Menu/menu.xml"));pMenu->Init(*this, pt);pMenu->ShowWindow(TRUE);}}

还有最重要的一步就是把图片资源解压到exe目录啦,下载资源猛戳这里~(注意:此处已给出所有的资源和代码,后面的教程将不再重复提供资源下载)

好啦,菜单按钮是不是和MFC的很像呢,还有阴影哦~O(∩_∩)O~

(更丰富的菜单样式请参阅duilib自带的MenuDemo)

【菜单类小知识】

如果不用指针的方式,而直接用变量的方式显示菜单 CDuiMenu menu(_T("Menu/menu.xml")),则不能用ShowWindow,否则会崩溃,因为出了作用域后窗口被销毁了,所以此时可以将CDuiMenu 定义为成员变量、全局变量、或者静态变量,但是做为一个局部使用的类,这些方法显然不怎么好;

这时可以用ShowModal代替ShowWindow,于是就能看到窗口啦,但是却产生了一个问题,那就是菜单窗口不会失去焦点,或者说点击主窗口的其他区域,菜单不会消失,当然,小伙伴们可以自己捕获鼠标,来判断是否点击了主窗口的其他区域,但显然这种方法也不太好;

这个时候delete this就派上用场啦(用智能指针也会崩溃,因为出了作用域同样会销毁内存,所以只能用delete this啦~ 用delete this就是将作用域交给duilib了),据说COM里面就是用delete this来销毁内存的。Alberl在duilib的Demo里面见到了大量的delete this,觉得这种自杀的方法很不靠谱,这不,前面教程就提到了ActiveX的一个bug,也是和delete this脱不了干系的~  不过既然COM里面都用了delete this,那就说明如果用好这把双刃剑,还是可以带来很多好处的。

因为duilib提供了一个机制,就是窗口的最后一个函数一定是OnFinalMessage,之后不再调用窗口类的其他函数,这就为自杀提供了两个必要条件;delete this而还有一个必要条件就是这个类必须是通过new来申请内存的(而非 "new[]",亦非placement的"new" ,一定要是最原始的 "new",当然malloc也行(需要用free,而不是delete)),所以就将析构函数设置成私有函数,就保证了只有通过new申请内存的方式才能编译通过。 而duilib的Demo中大量使用delete this却没有保证这些必要条件,只要直接用变量的方式来声明类,则关闭窗口时就会崩溃,作为Demo,如此不严谨,有待好好规范。 当然,没有XX党,就没有新中国,没有那些大神的Demo,也就轮不到Alberl唧唧歪歪啦,这里Alberl只是觉得Demo应该严谨和权威,毕竟是官方的,并没有其他意思,请多多谅解~O(∩_∩)O~

二、组合框控件

由于duilib也没有自带GroupBox,所以我们一般采用的是Label + Control的组合,迅雷、百度、金山快盘、华为网盘这些都是这种组合,如图:

这个就不用代码了吧,左边的Label 设置文字颜色,右边的Control设置背景色,高度设置为1就好了。

三、复选框、单选框

duilib的TestApp1中有几个CheckBox,不过也是需要图片资源的,因为图中的方框就是图片模拟的,代码也很简单,后面的教程会有详细的代码~

四、时间选择控件

这个也很简单,代码如下:

<DateTime name="DateTimeDemo1" float="true" pos="30,118,0,0" width="120" height="30" bkcolor="#FFE2E5EA" padding="0,5,0,0" /> 

五、RichList、树形控件

经过前面教程详细的介绍,相信现在已经基本入门了,由于Alberl暂时也没看这些控件,所以请自行参阅duilib自带的Demo。

RichList请参阅duilib自带的RichListDemo,效果如图:

Tree控件请参阅 (QQDemo、GameDemo,TestApp1),效果如图:

duilib的控件就基本介绍完啦,其他控件也请自行参阅~O(∩_∩)O~

结合Win32和MFC

虽然duilib自带在MFC中使用duilib的Demo,但只是MFC窗口和duilib窗口不重叠的情况。如果要在MFC窗口中嵌入duilib控件,或者在duilib控件中嵌入MFC的控件的话,就没有Demo可以看了,其实Alberl开始也不知道怎么办,看了下ActiveXUI控件,这个就是结合HWND的,但是由于接触duilib不久,所以一时无法看懂ActiveXUI到底是怎么将win32的HWND画上去的,只好在群里问啦,多谢铅笔群的Troy大神指导:

当时解决完之后上传了代码,不过还是有网友看不懂,于是昨晚要求Alberl先写duilib结合MFC的教程,当然啦,这个教程本来就在Alberl的计划之类,所以就折中一下啦,上一篇教程只写了一半,等写完这个教程再去补充,如果小伙伴们还有其他要求,也可以提哦,如果在Alberl的计划内,Alberl会尽量满足小伙伴们的要求的~O(∩_∩)O~

一、在MFC中使用duilib

只需要将前面教程的CDuiFrameWnd的父窗口指定为MFC的窗口就好啦,

将CDuiFrameWnd m_duiFrame; 定义为MFC的成员变量,在MFC的初始化函数OnInitDialog里面创建duilib的窗口,代码如下:

 // TODO: 在此添加额外的初始化代码CPaintManagerUI::SetInstance(AfxGetInstanceHandle());                    // 指定duilib的实例CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());    // 指定duilib资源的路径,这里指定为和exe同目录::CoInitialize(NULL);  // 记得释放::CoUninitialize();m_duiFrame.Create(*this, _T("DUIWnd"), UI_WNDSTYLE_CHILD, 0, 0, 0, 800, 600); m_duiFrame.ShowWindow(TRUE); return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE

这里只是将duilib嵌入到MFC的主窗口,如果想要将duilib嵌入到MFC的某个控件,也是很简单的,因为只需要一个HWND句柄就行了,就不赘述了~

不过可以发现以下几个问题:

1、之前ActiveXUI的那个bug不再出现了。

2、所有的MFC控件都显示在duilib窗口的上面,这里和ZORD顺序应该有关系。

3、在duilib窗口上面的【确定】按钮点了没反应,【取消】按钮只有在点击不在duilib上面的那部分才会有反应。

由于Alberl暂时只是研究界面方面,还没研究到事件响应方面,所以不去研究细节。如果有小伙伴急用的话,可以将MFC控件嵌入到duilib的控件上,或者把MFC控件放到非duilib区域,这样就可以响应了。

二、在duilib中使用MFC控件

这里示例将MFC按钮放到duilib滑块条控件的位置:

1、准备好一个duilib控件来容纳MFC控件,代码如下:

// 将带句柄HWND的控件显示到CControlUI上面
class CWndUI: public CControlUI
{
public:CWndUI(): m_hWnd(NULL){}virtual void SetInternVisible(bool bVisible = true){__super::SetInternVisible(bVisible);::ShowWindow(m_hWnd, bVisible);}virtual void SetPos(RECT rc){__super::SetPos(rc);::SetWindowPos(m_hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE);}BOOL Attach(HWND hWndNew){if (! ::IsWindow(hWndNew)){return FALSE;}m_hWnd = hWndNew;return TRUE;}HWND Detach(){HWND hWnd = m_hWnd;m_hWnd = NULL;return hWnd;}protected:HWND m_hWnd;
};

2、将XML中Slider节点换成Wnd,并且只保留位置信息,XML如下:

<Wnd float="true" pos="30,77,0,0" width="139" height="18" />

3、创建Wnd控件:由于Slider是duilib内置的控件,所以duilib会根据XML信息自动创建Slider控件,而CWndUI是我们自定义的控件,所以需要自己创建,只需要响应CreateControl函数(如果duilib发现自定义控件,会自动调用此函数来获取控件),在CDuiFrameWnd加上如下函数:

virtual CControlUI* CreateControl(LPCTSTR pstrClassName){if (_tcsicmp(pstrClassName, _T("Wnd")) == 0){CWndUI  *pUI  = new CWndUI;            HWND    hWnd  = CreateWindow(_T("BUTTON"), _T("win32"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 0, 0, 0, m_PaintManager.GetPaintWindow(), NULL, NULL, NULL);pUI->Attach(hWnd);  上面用的是win32的按钮,下面这段用MFC的按钮//CButton *pBtn = new CButton;    // 记得释放内存//pBtn->Create(_T("MFC"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, CRect(0, 0, 0, 0), CWnd::FromHandle(m_PaintManager.GetPaintWindow()), 0);//pUI->Attach(*pBtn);            return pUI;}return NULL;}

上面的代码用了win32的按钮,其中注释部分是MFC按钮,亲们可以都试下效果:

到现在为止,我们既可以在duilib中添加MFC控件,也可以在原有的MFC项目中添加duilib控件,就不用再担心不能使用以前的控件啦~O(∩_∩)O~

事件处理和响应消息

界面的显示方面就都讲完啦,下面来介绍下控件的响应。

前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理。其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEGIN_MESSAGE_MAP,可以将DUI_MSGTYPE_CLICK消息映射到指定的函数(比如OnClick),这和在Notify判断msg.sType是一样的效果,具体请参见duilib的RichListDemo。

先看看下面几段代码:

DUI_BEGIN_MESSAGE_MAP(CPage1, CNotifyPump)DUI_ON_MSGTYPE(DUI_MSGTYPE_CLICK,OnClick)DUI_ON_MSGTYPE(DUI_MSGTYPE_SELECTCHANGED,OnSelectChanged)DUI_ON_MSGTYPE(DUI_MSGTYPE_ITEMCLICK,OnItemClick)
DUI_END_MESSAGE_MAP()
LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{LRESULT lRes = 0;BOOL bHandled = TRUE;switch (uMsg){case WM_KEYDOWN:        lRes = OnKeyDown(uMsg, wParam, lParam, bHandled); break;case WM_LBUTTONDOWN:    lRes = OnLButtonDown(uMsg, wParam, lParam, bHandled); break;case WM_MOUSEMOVE:      lRes = OnMouseMove(uMsg, wParam, lParam, bHandled); break;default:                bHandled = FALSE; break;}if (bHandled) return lRes;return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
}

我们再来看看MFC的两段代码:

BEGIN_MESSAGE_MAP(CMFCDlg, CDialog)ON_BN_CLICKED(IDC_BUTTON_ADD_FILES, &CMFCDlg::OnBnClickedButtonAddFiles)ON_BN_CLICKED(IDC_BUTTON_CLEAR_FILES, &CMFCDlg::OnBnClickedButtonClearFiles)ON_BN_CLICKED(IDC_BUTTON_DELETE_FILES, &CMFCDlg::OnBnClickedButtonDeleteFiles)
END_MESSAGE_MAP()
LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{LRESULT lRes = 0;switch (uMsg){case WM_KEYDOWN:        lRes = OnKeyDown(uMsg, wParam, lParam, bHandled); break;case WM_LBUTTONDOWN:    lRes = OnLButtonDown(uMsg, wParam, lParam, bHandled); break;case WM_MOUSEMOVE:      lRes = OnMouseMove(uMsg, wParam, lParam, bHandled); break;default:                break;}return CDialog::DefWindowProc(uMsg, wParam, lParam);
}

很明显,duilib参考了MFC、ATL/WTL的消息机制:

1、DUI_BEGIN_MESSAGE_MAP类似于MFC的BEGIN_MESSAGE_MAP。

2、HandleMessage类似于MFC的DefWindowProc。

不过需要注意参数bHandled,这个参数是模仿ATL的。bHandled在ATL中的作用如下:

在消息响应函数调用前被ATL设置为TRUE,如果在你的消息响应处理完之后需要ATL调用默认的WindowProc()处理该消息,你可以将bHandled设置为FALSE。这与MFC不同, MFC是显式地调用基类的响应函数来实现的默认的消息处理的。

3、不过duilib还提供了另外一个函数,即Notify函数,Notify用于处理duilib自己定义的一套消息,其消息类型请参见duilib的UIDefine.h:

//定义所有消息类型
//#define DUI_MSGTYPE_MENU                   (_T("menu"))
#define DUI_MSGTYPE_LINK                   (_T("link"))#define DUI_MSGTYPE_TIMER                  (_T("timer"))
#define DUI_MSGTYPE_CLICK                  (_T("click"))#define DUI_MSGTYPE_RETURN                 (_T("return"))
#define DUI_MSGTYPE_SCROLL                 (_T("scroll"))#define DUI_MSGTYPE_DROPDOWN               (_T("dropdown"))
#define DUI_MSGTYPE_SETFOCUS               (_T("setfocus"))#define DUI_MSGTYPE_KILLFOCUS              (_T("killfocus"))
#define DUI_MSGTYPE_ITEMCLICK              (_T("itemclick"))
#define DUI_MSGTYPE_TABSELECT              (_T("tabselect"))#define DUI_MSGTYPE_ITEMSELECT             (_T("itemselect"))
#define DUI_MSGTYPE_ITEMEXPAND             (_T("itemexpand"))
#define DUI_MSGTYPE_WINDOWINIT             (_T("windowinit"))
#define DUI_MSGTYPE_BUTTONDOWN             (_T("buttondown"))
#define DUI_MSGTYPE_MOUSEENTER             (_T("mouseenter"))
#define DUI_MSGTYPE_MOUSELEAVE             (_T("mouseleave"))#define DUI_MSGTYPE_TEXTCHANGED            (_T("textchanged"))
#define DUI_MSGTYPE_HEADERCLICK            (_T("headerclick"))
#define DUI_MSGTYPE_ITEMDBCLICK            (_T("itemdbclick"))
#define DUI_MSGTYPE_SHOWACTIVEX            (_T("showactivex"))#define DUI_MSGTYPE_ITEMCOLLAPSE           (_T("itemcollapse"))
#define DUI_MSGTYPE_ITEMACTIVATE           (_T("itemactivate"))
#define DUI_MSGTYPE_VALUECHANGED           (_T("valuechanged"))#define DUI_MSGTYPE_SELECTCHANGED          (_T("selectchanged"))

到这里,duilib的消息机制就很明朗啦,只要熟悉windows消息机制的,稍微看看Demo就懂啦;不熟悉windows消息机制的,一时半会就说不清楚啦,还请先学习好 【2013 duilib入门简明教程 -- VS环境配置(2)】中推荐的资料吧~O(∩_∩)O~

其他

一、超链接按钮

代码很简单,参见360Demo:

<Button text="{u}{a}求助{/a}{/u}" showhtml="true"/>

这里只需要加上showhtml="true",然后在text属性里写类html代码就可以了,不过duilib只支持小部分html代码,具体的格式请参见Demo以及源码~

二、支持html

由于html非常方便,所以duilib也提供了部分支持,上面的超链接按钮就是使用html来表示,在360Demo里面有大量的html支持,详情请参阅Demo,效果如图:

三、改变字体

前面介绍了Default属性,属于全局属性,而字体也是全局属性,也是定义到一级子节点。

<Font name="20号字体" size="20" bold="false" italic="false" />

<Font name="15号字体" size="15" bold="false" italic="false" />

序号从0开始,上述顺序中,第0个字体就是name为【20号字体】的字体,所以如果想用这个字体,只需要在控件的属性里指定字体序号即可,如:

<Button text="字体测试" font="0"/>

四、duilib的其他操作依然是win32的做法

1、设置exe的图标

导入一个icon资源即可,操作步骤如下:

运行之后就可以看到exe的图标和任务栏的图标都变了~

注意:如果任务栏的图标没变,则需要调用 SetIcon(IDR_MAINFRAME); // 设置任务栏图标 (其中IDR_MAINFRAME是图标的ID)

2、设置公司、产品名、描述、版本等信息

在任务管理器中可以看到很多exe的描述,此Demo的描述是Duilib Tutorial.exe

如果想将它改成其他名字,则需要按如下操作添加一个Version资源

在Version里修改相应信息即可

修改后的结果如下:

3、设置托盘等其他操作也都是win32的做法,就不一一说明了。

参考:2013 duilib入门简明教程 -- 总结 (20) - Alberl - 博客园

Duilib介绍-3相关推荐

  1. Duilib介绍-2

    部分BUG 一.WindowImplBase的bug 在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题, 1.最大化按钮的样式还是没 ...

  2. 使用Duilib做桌面应用总结

    使用Duilib做桌面应用总结 最近使用Duilib做了一个简单的桌面应用,在此做一个简单的总结,一是为了记录自己的学习过程,二是对Duilib的使用做一个简单的总结以便后期使用时查阅. Duilib ...

  3. 一.Duilib开发之基本使用

    一. Duilib介绍 Duilib是一款轻量级,遵循BSD协议的开源C++ GUI框架,可以免费用于商业项目,是由杭州月牙儿网络技术有限公司基于DirectUI界面思想设计出来的GUI开源框架:所谓 ...

  4. 全网首发:网易云信Duilib 源码编译教程以及可执行演示包下载

    序言 Duilib介绍 Duilib是windows平台下的一款轻量级directUI开源库(遵循BSD协议),完全免费,可用于商业软件开发,只需在软件包里附上协议文件即可.Duilib可以简单方便地 ...

  5. xpsql.cpp: 错误 5 来自 CreateProcess

    消息 50001,级别 1,状态 50001 xpsql.cpp: 错误 5 来自 CreateProcess(第 737 行) 这个错误是因为 cmd设置了权限导致. 下面给些突破的方法吧 ---- ...

  6. Duilib教程-简单介绍

    在读这篇博客的时候,可能您已经对duilib有一定的了解.所以,我并不打算对duilib进行过多的介绍.它的内核首先由外国人编写,后来由国人一个小组接过来继续编写,于是就有了现在的Duilib. 1. ...

  7. duilib环境配置以及简单入门介绍

    内容全部为转载: VS2013的编译,https://www.cnblogs.com/Alberl/p/3342030.html duilib框架介绍,以及VS2013配置,创建工程,调试代码部分: ...

  8. duilib消息机制的介绍

    参考:https://www.cnblogs.com/redrainblog/p/4209721.html

  9. duilib拖动控制功能的实现(源代码)

    转载请注明原始出处.谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/41144283 duilib库中原本没有显示的对控件添加拖拽的功能.而实 ...

  10. duilib入门简明教程 -- VS环境配置(2) (转)

    原文转自:http://www.cnblogs.com/Alberl/p/3342030.html     既然是入门教程,那当然得基础点,因为搜索duilib相关资料时,发现有些小伙伴到处都是编译错 ...

最新文章

  1. java web 自定义filter
  2. java rxtx version_java – 不匹配的RXTX版本
  3. 贝叶斯推断及其互联网应用(一)
  4. 【Python基础】为什么更改列表'y'也会更改列表'x'?
  5. awk -f 分隔符 命令_千面 awk
  6. Tomcat 配置Https
  7. 数据库Mysql的学习(六)-子查询和多表操作
  8. 计算机控制面板图标怎么删除,电脑如何找回消失的“添加或删除程序”图标
  9. go - 构造复杂json串
  10. 1.WebServices 简介
  11. JetBrains(Intellij, pycharm)多行编辑模式
  12. Python 2.6 升级到 2.7
  13. 【优化选址】基于matlab遗传算法求解多城市多应急物流中心选址优化问题【含Matlab源码 H001期】
  14. android编译log中_安卓编译 Jack server 错误问题解决办法
  15. 你离顶尖Java程序员,只差这11本书的距离 172 分享 分享到新浪微博 分享到QQ空间
  16. windows控制台命令: 快捷键大集合
  17. Python爬虫实战:《战狼2》豆瓣影评分析
  18. 蓝桥杯练习——摔手机测试次数
  19. 【畅购商城】 B2B、 C2C、B2C、C2B、O2O、B2B2C电商模式介绍与分析
  20. 软件开发中,做产品与做项目有什么区别?

热门文章

  1. 运行在网络处理器上的嵌入式Linux系统
  2. 工程师原创:人人都看得懂的电磁场理论
  3. rs485数据线接反_rs485接口怎么接线?弱电人必学RS485接口基础知识讲解
  4. 第 1 章 程序员考试简介
  5. 1.16 隐藏不需要打印的内容 [原创Excel教程]
  6. 专业卸载工具Your Uninstaller! Pro
  7. 金士顿DT100G3(16G) U盘修复
  8. 如何下载安装fireBug
  9. FastDFS——Bug篇——上传txt文档乱码
  10. yansongda/pay 支付遇到的坑