⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 关于用vc,vb进行图像数据(二进制大对象)存储数据库的一点心得 .htm

📁 数据库编程技巧文章
💻 HTM
字号:
<HTML>
<HEAD>
<meta http-equiv='Content-Type' content='text/html; charset=gb2312'>
<meta HTTP-EQUIV='Expires' CONTENT=0>
<link rel='stylesheet' href='../../../../news.css'>
<style type='text/css'>
.fst{padding:0px 15px;width:770px;background:#eeeecc;border-left:1px solid #000000;border-right:1px solid #000000}
.fstdiv3 img{border:0px;border-right:8px solid #eeeecc;border-top:6px solid #eeeecc}
</style>
<title>
关于用VC,VB进行图像数据(二进制大对象)存储数据库的一点心得
</title>
</HEAD>
<BODY aLink=#990000 bgColor=#ffffff bottomMargin=0 leftMargin=0  rightMargin=0 topMargin=0  marginwidth=0 marginheight=0>
<center>

<TABLE align=center bgColor=#cccc99 border=0 cellPadding=2 cellSpacing=0  width=770>
<TBODY>
<TR>
<TH align=left >
关于用VC,VB进行图像数据(二进制大对象)存储数据库的一点心得
&nbsp;&nbsp;&nbsp;
</TH>
</TD></TR>
</TBODY></TABLE>
<TABLE align=center bgColor=#eeeecc border=1 cellPadding=1 cellSpacing=0  width=770>
<TBODY>
<TR><TD colSpan=5 >&nbsp;
<a href='http://www.csdn.net'>中国软件开发网络</a>
-->
<a href='http://www.csdn.net/develop'>开发图书馆</a>
-->
<a href='http://www.csdn.net\develop\list_article.asp?lib=1&bigclassid=
1
'>
Visual C++
</a>
-->
<a href='http://www.csdn.net\develop\list_article.asp?lib=1&bigclassid=
1
&smallclassid=
107
'>
数据库操作
</a>
-->
<a href='
http://www.csdn.net/develop/library/vc/datebase/6863.shtm
'>
关于用VC,VB进行图像数据(二进制大对象)存储数据库的一点心得
</a>
</TD></tr>
<TR>
<TD align=left   width=300>
<B>关键字:</B><BR>
ADO,BLOB,图像数据
</TD>
<TD align=middle   width=120>
<B>贴文时间</B><br>
2001-5-5 16:05:09
</TD>
<TD align=middle   width=80>
<B>文章类型: </B><BR>
原作
</TD>
<TD align=middle   width=100>
<B>给贴子投票 </B>
<BR><a href='http://www.csdn.net/develop/addscore.asp?id=
6863
'>投票</a>
</TD></TR>
<TR>
<TD >
&nbsp;
bluestar
&nbsp;&nbsp;
原作
</TD>
<TD   colSpan=3 vAlign=top>
<B>出处: </B><A href='

'>

</A></TD></TR>
<TR><TD  colSpan=5 bgcolor=#cccc99>&nbsp;</TD></TR>
</TD></TR></TBODY></TABLE>
<div align=center><div class=fst align=left><div class=fstdiv3 id=print2>
<br><br><P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网上经常有人问如何把图像存入数据库中,原先我也是不得要领。经过多方指点和自己在开发过程中的摸索,终于解决这一问题。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面给出用VC,VB如何操作图像文件存取数据库的原码,帮助一些还没有掌握方法的朋友,也请这方面的高手多多指教。(均用ADO连接数据库)</P>
<P><FONT face=System>1. VC把一个文件存入数据库</FONT></P>
<P><FONT face=System>&nbsp; CFile imagefile;<BR>&nbsp;&nbsp;if(0 == imagefile.Open("d:\\user\\bmp.bmp",CFile::modeRead))<BR>&nbsp;&nbsp;&nbsp;&nbsp; return;<BR>&nbsp;&nbsp;_RecordsetPtr pRs = NULL;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;_ConnectionPtr pConnection = NULL;<BR>&nbsp;&nbsp;_variant_t varChunk;<BR>&nbsp;&nbsp;HRESULT hr;<BR>&nbsp;&nbsp;BYTE* pbuf;<BR>&nbsp; long nLength = imagefile.GetLength();<BR>&nbsp;&nbsp;pbuf = new BYTE[nLength+2];<BR>&nbsp;&nbsp;if(pbuf == NULL)<BR>&nbsp;&nbsp;&nbsp;&nbsp; return;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //allocate memory error;<BR>&nbsp;&nbsp;imagefile.Read(pbuf,nLength);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //read the file into memory</FONT></P>
<P><FONT face=System>&nbsp;&nbsp;BYTE *pBufEx;<BR>&nbsp;&nbsp;pBufEx = pbuf;<BR>&nbsp;&nbsp;//build a SAFFERRAY<BR>&nbsp;&nbsp;SAFEARRAY* psa;<BR>&nbsp;&nbsp;SAFEARRAYBOUND rgsabound[1];<BR>&nbsp;&nbsp;rgsabound[0].lLbound = 0;<BR>&nbsp;&nbsp;rgsabound[0].cElements = nLength;<BR>&nbsp;&nbsp;psa = SafeArrayCreate(VT_UI1, 1, rgsabound);</FONT></P>
<P><FONT face=System>&nbsp;&nbsp;for (long i = 0; i &lt; nLength; i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SafeArrayPutElement (psa, &amp;i, pBufEx++);<BR>&nbsp;&nbsp;VARIANT varBLOB;<BR>&nbsp;&nbsp;varBLOB.vt = VT_ARRAY | VT_UI1;<BR>&nbsp;&nbsp;varBLOB.parray = psa;</FONT></P>
<P><FONT face=System>&nbsp;&nbsp;_bstr_t strCnn("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER");&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; try<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Open a connection<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pConnection.CreateInstance(__uuidof(Connection));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;hr = pConnection-&gt;Open(strCnn,"","",NULL);&nbsp;&nbsp; //Connect a DataBase<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;pRs.CreateInstance(__uuidof(Recordset));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;pRs-&gt;Open("CustomInfo",_variant_t((IDispatch *) pConnection,true),adOpenKeyset,adLockOptimistic,adCmdTable);&nbsp; //Open a Table<BR>&nbsp;<BR>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRs-&gt;AddNew();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRs-&gt;Fields-&gt;GetItem("Image")-&gt;AppendChunk(varBLOB);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRs-&gt;Update();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRs-&gt;Close();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pConnection-&gt;Close();<BR>&nbsp;}<BR>&nbsp;&nbsp;&nbsp; catch(_com_error &amp;e)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Notify the user of errors if any.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _bstr_t bstrSource(e.Source());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _bstr_t bstrDescription(e.Description());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CString sError;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sError.Format("Source : %s \n Description : %s\n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AfxMessageBox(sError);&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;}</FONT></P>
<P><FONT face=System>2. VC把数据库中IMAGE字段取出存为文件</FONT></P>
<P><FONT face=System>&nbsp;&nbsp;&nbsp; _RecordsetPtr pRs = NULL;<BR>&nbsp;&nbsp;&nbsp; _ConnectionPtr pConnection = NULL;<BR>&nbsp;&nbsp;&nbsp; _variant_t varChunk;<BR>&nbsp;&nbsp;&nbsp; HRESULT hr;<BR>&nbsp;&nbsp;&nbsp; VARIANT varBLOB;<BR>&nbsp;&nbsp; &nbsp;_bstr_t strCnn("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER");&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; try<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Open a connection<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pConnection.CreateInstance(__uuidof(Connection));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;hr = pConnection-&gt;Open(strCnn,"","",NULL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;pRs.CreateInstance(__uuidof(Recordset));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pRs-&gt;Open("CustomInfo",_variant_t((IDispatch *) pConnection,true),adOpenKeyset,adLockOptimistic,adCmdTable);<BR>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;//read&nbsp; data&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;long lDataLength = pRs-&gt;Fields-&gt;GetItem("Image")-&gt;ActualSize;<BR>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;varBLOB = pRs-&gt;GetFields()-&gt;GetItem("Image")-&gt;GetChunk(lDataLength);<BR>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;if(varBLOB.vt == (VT_ARRAY | VT_UI1))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp; &nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BYTE *pBuf = NULL;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pBuf = (BYTE*)GlobalAlloc(GMEM_FIXED,lDataLength);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;SafeArrayAccessData(varBLOB.parray,(void **)pBuf);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//Build a File in Windows Temp Directory<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;char tmpPath[_MAX_PATH+1];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GetTempPath(_MAX_PATH,tmpPath);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CString strFileName = "temp.bmp";<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strFileName = tmpPath+strFileName;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CFile outFile(strFileName,CFile::modeCreate|CFile::modeWrite);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pBuf);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outFile.WriteHuge(buffer,lDataLength);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GlobalUnlock((HGLOBAL)pBuf);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outFile.Close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SafeArrayUnaccessData (varBLOB.parray);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</FONT></P>
<P><FONT face=System>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pRs-&gt;Close();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pConnection-&gt;Close();<BR>&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; catch(_com_error &amp;e)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Notify the user of errors if any.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _bstr_t bstrSource(e.Source());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _bstr_t bstrDescription(e.Description());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CString sError;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sError.Format("Source : %s \n Description : %s\n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AfxMessageBox(sError);&nbsp;&nbsp;&nbsp;&nbsp; <BR>&nbsp;}&nbsp;</FONT></P>
<P><FONT face=System>3. VB把文件存入数据库IMAGE字段</FONT></P>
<P><FONT face=System>Sub savepic(FileName As String, IndexNumber As Long)<BR>&nbsp;&nbsp; Dim DcnNWind As New ADODB.Connection<BR>&nbsp;&nbsp; Dim rs As ADODB.Recordset<BR>&nbsp;&nbsp; Set rs = New ADODB.Recordset<BR>&nbsp;&nbsp; DcnNWind.CursorLocation = adUseClient<BR>&nbsp;&nbsp; DcnNWind.Open "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER"<BR>&nbsp;&nbsp; rs.CursorType = adOpenKeyset<BR>&nbsp;&nbsp; rs.LockType = adLockOptimistic<BR>&nbsp;&nbsp; rs.Open "CustomInfo", DcnNWind, , adCmdTable<BR>&nbsp;&nbsp; rs.Move (IndexNumber)<BR>&nbsp;&nbsp; Call FileToBlob(rs.Fields("Image"), FileName, FileLen(FileName))<BR>&nbsp;&nbsp; rs.UpdateBatch adAffectCurrent<BR>End Sub</FONT></P>
<P><FONT face=System>Private Sub FileToBlob(fld As ADODB.Field, FileName As String, Optional ChunkSize As Long )<BR>&nbsp;&nbsp; Dim fnum As Integer, bytesLeft As Long, bytes As Long<BR>&nbsp;&nbsp; Dim tmp() As Byte<BR>&nbsp;&nbsp; If (fld.Attributes And adFldLong) = 0 Then<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Err.Raise 1001, , "Field doesn't support the GetChunk method."<BR>&nbsp;&nbsp; End If<BR>&nbsp;&nbsp; fnum = FreeFile<BR>&nbsp;&nbsp; Open FileName For Binary As fnum<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesLeft = LOF(fnum)<BR>&nbsp;&nbsp; Do While bytesLeft<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytes = bytesLeft<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If bytes &gt; ChunkSize Then bytes = ChunkSize<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReDim tmp(1 To bytes) As Byte<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get #1, , tmp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fld.AppendChunk tmp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesLeft = bytesLeft - bytes<BR>&nbsp;&nbsp; Loop<BR>&nbsp;&nbsp; Close #fnum<BR>End Sub</FONT></P>
<P><FONT face=System>4. VB把文件从IMAGE字段中读到文件中。</FONT></P>
<P><FONT face=System>Sub loadpic(IndexNumber As Long)<BR>&nbsp;&nbsp; Dim DcnNWind As New ADODB.Connection<BR>&nbsp;&nbsp; Dim rs As ADODB.Recordset<BR>&nbsp;&nbsp; Set rs = New ADODB.Recordset<BR>&nbsp;&nbsp; DcnNWind.CursorLocation = adUseClient<BR>&nbsp;&nbsp; DcnNWind.Open "Provider=SQLOLEDB.1;Integrated Security=SSI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER"<BR>&nbsp;&nbsp; rs.CursorType = adOpenKeyset<BR>&nbsp;&nbsp; rs.LockType = adLockOptimistic<BR>&nbsp;&nbsp; rs.Open "CustomInfo", DcnNWind, , adCmdTable<BR>&nbsp;&nbsp; rs.Move (IndexNumber)<BR>&nbsp;&nbsp; Call BlobToFile(rs.Fields("Image"), "c:\windows\temp\tmp.bmp", rs.Fields("Image").ActualSize)<BR>End Sub</FONT></P>
<P><FONT face=System>Private Sub BlobToFile(fld As ADODB.Field, FileName As String, Optional ChunkSize As Long&nbsp;)<BR>&nbsp;&nbsp; Dim fnum As Integer, bytesLeft As Long, bytes As Long<BR>&nbsp;&nbsp; Dim tmp() As Byte<BR>&nbsp;&nbsp; If (fld.Attributes And adFldLong) = 0 Then<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Err.Raise 1001, , "Field doesn't support the GetChunk method."<BR>&nbsp;&nbsp; End If<BR>&nbsp;&nbsp; If Dir$(FileName) &lt;&gt; "" Then Kill FileName<BR>&nbsp;&nbsp; fnum = FreeFile<BR>&nbsp;&nbsp; Open FileName For Binary As fnum<BR>&nbsp;&nbsp; bytesLeft = fld.ActualSize<BR>&nbsp;&nbsp; Do While bytesLeft<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytes = bytesLeft<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If bytes &gt; ChunkSize Then bytes = ChunkSize<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp = fld.GetChunk(bytes)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Put #fnum, , tmp<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytesLeft = bytesLeft - bytes<BR>&nbsp;&nbsp; Loop<BR>&nbsp;&nbsp; Close #fnum<BR>End Sub</FONT></P><br><br>
</DIV></div></div>
<script src='../../../get_readnum.asp?id=
6863
'></script>
</center></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -