<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1721523466657532879</id><updated>2025-06-30T10:27:14.086+10:00</updated><category term="MFC"/><category term="Android"/><category term="C"/><category term="Coding IDE"/><category term="OpenGL"/><category term="Win"/><category term="WinApi"/><category term="C++"/><category term="CTreeCtrl"/><category term="Eclipse"/><category term="Animation"/><category term="Unity(3.5.6f4)"/><category term="Windows"/><category term="引用參考"/><category term="C#"/><category term="GWT"/><category term="JAR"/><category term="Katalon"/><category term="PHP"/><category term="Tutorial"/><category term="Twig"/><category term="Unity Plugins"/><category term="Unity(3.5.7f6)"/><category term="A_Func"/><category term="Activation"/><category term="Animation Clip"/><category term="AnimationState"/><category term="Ant"/><category term="Apache"/><category term="Blogger Tool"/><category term="CDialog"/><category term="CTreeCtrk"/><category term="CTreeList"/><category term="Code Highlight"/><category term="Docker Buildx"/><category term="Dockerfile"/><category term="GCP"/><category term="Google App Engine"/><category term="Google Cloud Platform"/><category term="Gralde"/><category term="Input"/><category term="Linux function"/><category term="Mac OS X 10.11.3"/><category term="Markdown"/><category term="Menu"/><category term="Network"/><category term="SDK Tools"/><category term="Service"/><category term="Testing"/><category term="Texture Mapping"/><category term="ToolTip"/><category term="Tools"/><category term="Twig Packs"/><category term="Unity"/><category term="Visual Studio Code"/><category term="Visual Studio Code Extensions"/><category term="Web App"/><category term="java"/><category term="memo"/><title type='text'>Otto&#39;s Coding Notes</title><subtitle type='html'>I learned what I saw whatever it is</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>95</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-3745980830145226929</id><published>2022-08-24T19:22:00.015+10:00</published><updated>2022-08-25T15:03:21.414+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Docker Buildx"/><category scheme="http://www.blogger.com/atom/ns#" term="Dockerfile"/><category scheme="http://www.blogger.com/atom/ns#" term="Markdown"/><title type='text'>Build docker image from multiple build contexts</title><content type='html'>&lt;!DOCTYPE html&gt;
    &lt;html&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;UTF-8&quot;&gt;
        &lt;title&gt;Build docker image from multiple build contexts&lt;/title&gt;
        &lt;style&gt;
/* From extension vscode.github */
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

.vscode-dark img[src$=\#gh-light-mode-only],
.vscode-light img[src$=\#gh-dark-mode-only] {
	display: none;
}

/* From extension vscode.markdown-math */
@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(fonts/KaTeX_AMS-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_AMS-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_AMS-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Caligraphic-Bold.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Caligraphic-Bold.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Caligraphic-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Caligraphic-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Fraktur-Bold.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Fraktur-Bold.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Fraktur-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Fraktur-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Main-Bold.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Main-Bold.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Main-Bold.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Main-BoldItalic.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Main-BoldItalic.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Main-Italic.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Main-Italic.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Main-Italic.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Main-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Main-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Main-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Math-BoldItalic.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Math-BoldItalic.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Math-Italic.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Math-Italic.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Math-Italic.ttf) format(&quot;truetype&quot;)}@font-face{font-family:&quot;KaTeX_SansSerif&quot;;font-style:normal;font-weight:700;src:url(fonts/KaTeX_SansSerif-Bold.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_SansSerif-Bold.woff) format(&quot;woff&quot;),url(fonts/KaTeX_SansSerif-Bold.ttf) format(&quot;truetype&quot;)}@font-face{font-family:&quot;KaTeX_SansSerif&quot;;font-style:italic;font-weight:400;src:url(fonts/KaTeX_SansSerif-Italic.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_SansSerif-Italic.woff) format(&quot;woff&quot;),url(fonts/KaTeX_SansSerif-Italic.ttf) format(&quot;truetype&quot;)}@font-face{font-family:&quot;KaTeX_SansSerif&quot;;font-style:normal;font-weight:400;src:url(fonts/KaTeX_SansSerif-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_SansSerif-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_SansSerif-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Script-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Script-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Script-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size1-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Size1-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Size1-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size2-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Size2-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Size2-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size3-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Size3-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Size3-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size4-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Size4-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Size4-Regular.ttf) format(&quot;truetype&quot;)}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format(&quot;woff2&quot;),url(fonts/KaTeX_Typewriter-Regular.woff) format(&quot;woff&quot;),url(fonts/KaTeX_Typewriter-Regular.ttf) format(&quot;truetype&quot;)}.katex{text-rendering:auto;font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:&quot;0.13.24&quot;}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html&gt;.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist&gt;span{display:block;height:0;position:relative}.katex .vlist&gt;span&gt;span{display:inline-block}.katex .vlist&gt;span&gt;.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac&gt;span&gt;span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap&gt;.inner,.katex .llap&gt;.inner,.katex .rlap&gt;.inner{position:absolute}.katex .clap&gt;.fix,.katex .llap&gt;.fix,.katex .rlap&gt;.fix{display:inline-block}.katex .llap&gt;.inner{right:0}.katex .clap&gt;.inner,.katex .rlap&gt;.inner{left:0}.katex .clap&gt;.inner&gt;span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt&gt;.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1&gt;span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4&gt;span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent&gt;.vlist-t,.katex .op-limits&gt;.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c&gt;.vlist-t{text-align:center}.katex .mtable .col-align-l&gt;.vlist-t{text-align:left}.katex .mtable .col-align-r&gt;.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:&quot;&quot;}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:&quot;(&quot; counter(katexEqnNo) &quot;)&quot;;counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:&quot;(&quot; counter(mmlEqnNo) &quot;)&quot;;counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display&gt;.katex{display:block;text-align:center;white-space:nowrap}.katex-display&gt;.katex&gt;.katex-html{display:block;position:relative}.katex-display&gt;.katex&gt;.katex-html&gt;.tag{position:absolute;right:0}.katex-display.leqno&gt;.katex&gt;.katex-html&gt;.tag{left:0;right:auto}.katex-display.fleqn&gt;.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo}

/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

.katex-error {
	color: var(--vscode-editorError-foreground);
}

/* From extension ms-toolsai.jupyter */
/* These classnames are inherited from bootstrap, but are present in most notebook renderers */

.alert {
    width: auto;
    padding: 1em;
    margin-top: 1em;
    margin-bottom: 1em;
}
.alert &gt; *:last-child {
    margin-bottom: 0;
}
#preview &gt; .alert:last-child {
    /* Prevent this being set to zero by the default notebook stylesheet */
    padding-bottom: 1em;
}

.alert-success {
    /* Note there is no suitable color available, so we just copy &quot;info&quot; */
    background-color: var(--theme-info-background);
    color: var(--theme-info-foreground);
}
.alert-info {
    background-color: var(--theme-info-background);
    color: var(--theme-info-foreground);
}
.alert-warning {
    background-color: var(--theme-warning-background);
    color: var(--theme-warning-foreground);
}
.alert-danger {
    background-color: var(--theme-error-background);
    color: var(--theme-error-foreground);
}

blockquote {
  margin-left: 0;
  font: 8px;
}

&lt;/style&gt;
        &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css&quot; integrity=&quot;sha384-yFRtMMDnQtDRO8rLpMIKrtPCD5jdktao2TV19YiZYWMDkUR5GQZR/NOVTdquEx1j&quot; crossorigin=&quot;anonymous&quot;&gt;
&lt;link href=&quot;https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&gt;
        &lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css&quot;&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css&quot;&gt;
&lt;style&gt;
            body {
                font-family: -apple-system, BlinkMacSystemFont, &#39;Segoe WPC&#39;, &#39;Segoe UI&#39;, system-ui, &#39;Ubuntu&#39;, &#39;Droid Sans&#39;, sans-serif;
                font-size: 14px;
                line-height: 1.6;
            }
        &lt;/style&gt;
        &lt;style&gt;
.task-list-item { list-style-type: none; } .task-list-item-checkbox { margin-left: -20px; vertical-align: middle; }
&lt;/style&gt;
        
    &lt;/head&gt;
    &lt;body class=&quot;vscode-body vscode-light&quot;&gt;
	  &lt;p&gt;
        Building a docker image requires specifying a source of truth to include in the image from a local directory or a remote git repository. In the previous version, the docker BuildKit allows users to specify the build context from a single source of truth only. However, the engineers may need to have the context from different locations based on the type of files. For instance, icons, images or other resources that are not included in the same package, including the resource from other docker images. Fortunately, the Docker Buildx toolkit supports multiple build context flag for Docker 1.4. Let&#39;s learn how to use this new feature.
      &lt;/p&gt;
      &lt;p&gt;
        The following list is a shortcut for jumping into a specific topic handy.
      &lt;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#what-version-of-docker-is-this-tutorial-targeting&quot;&gt;What version of Docker is this tutorial targeting?&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#how-to-specify-the-version-of-dockerfile-frontend&quot;&gt;How to specify the version of &lt;code&gt;Dockerfile&lt;/code&gt; frontend?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#how-to-installupgrade-buildx&quot;&gt;How to install/upgrade &lt;code&gt;Buildx&lt;/code&gt;?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#why-do-we-need-the-build-context-flag&quot;&gt;Why do we need the Build Context flag?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#what-is-the-build-context-flag&quot;&gt;What is the Build Context flag?&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#load-build-context-from-a-local-directory&quot;&gt;Load build context from a Local Directory&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#load-build-context-via-relative-file-path&quot;&gt;Load build context via relative file path&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#combine-multiple-build-contexts&quot;&gt;Combine multiple build contexts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#load-build-context-via-absolute-file-path&quot;&gt;Load build context via absolute file path&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#load-build-context-from-a-git-repository&quot;&gt;Load build context from a Git repository&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#clone-the-git-repository-via-https&quot;&gt;Clone the git repository via HTTPS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#clone-the-git-repository-via-ssh&quot;&gt;Clone the git repository via SSH&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#load-build-context-from-a-tarball-via-http-url&quot;&gt;Load build context from a tarball via HTTP URL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#load-build-context-from-a-docker-image&quot;&gt;Load build context from a docker image&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#reference&quot;&gt;Reference&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;what-version-of-docker-is-this-tutorial-targeting&quot;&gt;What version of Docker is this tutorial targeting?&lt;/h1&gt;
&lt;p&gt;All of the examples and use cases are working against &lt;code&gt;Dockerfile&lt;/code&gt;
1.4 and &lt;code&gt;Buildx&lt;/code&gt; v0.8+. Please ensure the version of &lt;code&gt;Dockerfile&lt;/code&gt;
and &lt;code&gt;Buildx&lt;/code&gt; before starting this tutorial. If you would like to
install or upgrade the Docker Engine, please refers to&lt;br&gt;
&lt;a href=&quot;https://docs.docker.com/engine/install/&quot;&gt;Install Docker Engine&lt;/a&gt; page.&lt;/p&gt;
&lt;h2 id=&quot;how-to-specify-the-version-of-dockerfile-frontend&quot;&gt;How to specify the version of &lt;code&gt;Dockerfile&lt;/code&gt; frontend?&lt;/h2&gt;
&lt;p&gt;To specify the version of a &lt;code&gt;Dockerfile&lt;/code&gt; frontend, by adding a line of code at the top of the file as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# syntax=docker/dockerfile:1.4&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;## List other instructions below this line&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.docker.com/engine/reference/builder/#external-dockerfile-frontend&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;how-to-installupgrade-buildx&quot;&gt;How to install/upgrade &lt;code&gt;Buildx&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;It&#39;s very easy to install or upgrade &lt;code&gt;Buildx&lt;/code&gt; tool by executing:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx install
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/buildx_install/&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;why-do-we-need-the-build-context-flag&quot;&gt;Why do we need the Build Context flag?&lt;/h1&gt;
&lt;p&gt;To build an image by docker, the single build context from a local
repository is given from a path in the docker build command as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker build -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;However, this is not allowed to access files outside of specified
build context by using parent selector(&lt;code&gt;../&lt;/code&gt;) for security reasons.
This leads to the build context must be at the root directory,
sometimes it is not the project directory, if the developers would
like to build an image for an application referencing multiple
resources outside of the folder of an application. And it results in
many &lt;code&gt;COPY&lt;/code&gt; and &lt;code&gt;ADD&lt;/code&gt; instructions being written in the &lt;code&gt;Dockerfile&lt;/code&gt;
to achieve this goal, which reduces the readability of code.
Fortunately, &lt;code&gt;Dockerfile 1.4&lt;/code&gt; and &lt;code&gt;Buildx v0.8+&lt;/code&gt; support multiple
build context flags right now. This reduces the complexity of
&lt;code&gt;Dockerfile&lt;/code&gt; and provides more flexibility in organising build
contexts in the code with CI/CD pipeline.&lt;/p&gt;
&lt;h1 id=&quot;what-is-the-build-context-flag&quot;&gt;What is the Build Context flag?&lt;/h1&gt;
&lt;p&gt;Build context flag allows developers to define the build contexts
from &lt;code&gt;local directory&lt;/code&gt;, &lt;code&gt;Git repository&lt;/code&gt;, &lt;code&gt;HTTP URL&lt;/code&gt; and
&lt;code&gt;Docker Registry&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The syntax of the build context flag is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
  --build-context &lt;span class=&quot;hljs-variable&quot;&gt;${name}&lt;/span&gt;=&lt;span class=&quot;hljs-variable&quot;&gt;${pathToContext}&lt;/span&gt; \
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;${name}&lt;/code&gt; is the name of the build context, must be lowercase,
which will be used in the Dockerfile and the &lt;code&gt;${pathToContext}&lt;/code&gt;
is the location of the build context which could be
&lt;code&gt;local directory&lt;/code&gt;, &lt;code&gt;remote git repository&lt;/code&gt;,
&lt;code&gt;HTTP URL to a tarball&lt;/code&gt; and &lt;code&gt;Docker image&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also, &lt;code&gt;Dockerfile 1.4&lt;/code&gt; supports multiple build contexts for an
image by using:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker build \
  --build-context &lt;span class=&quot;hljs-variable&quot;&gt;${context1}&lt;/span&gt;=&lt;span class=&quot;hljs-variable&quot;&gt;${pathToContext1}&lt;/span&gt; \
  --build-context &lt;span class=&quot;hljs-variable&quot;&gt;${context2}&lt;/span&gt;=&lt;span class=&quot;hljs-variable&quot;&gt;${pathToContext2}&lt;/span&gt; \
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By using build context flags, developers can
copy the context outside of the project directory.&lt;/p&gt;
&lt;h2 id=&quot;load-build-context-from-a-local-directory&quot;&gt;Load build context from a Local Directory&lt;/h2&gt;
&lt;h3 id=&quot;load-build-context-via-relative-file-path&quot;&gt;Load build context via relative file path&lt;/h3&gt;
&lt;p&gt;Build context flag accepts relative file path and absolute file
path when the user would like to build an image from the files
in a local directory.&lt;/p&gt;
&lt;p&gt;The relative file path can be specified by the following two ways:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
  --build-context app=./workspaces/greeting \
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/local-directory/build_from_root.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-base&quot;&gt;&lt;code&gt;&lt;div&gt;docker buildx build \
  --build-context app=workspaces/greeting \
  -t ${imageName}:${tag} \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/local-directory/build_from_root_no_dot.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then using &lt;code&gt;COPY --from=${buildContextName}&lt;/code&gt; in the &lt;code&gt;Dockerfile&lt;/code&gt; to copy files:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; node:&lt;span class=&quot;hljs-number&quot;&gt;14.17&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;-alpine AS sourceStage
&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; /&lt;span class=&quot;hljs-built_in&quot;&gt;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --from=app [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;./&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/source/workspaces/greeting&amp;quot;&lt;/span&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/build-contexts/local-directory/Dockerfile&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;combine-multiple-build-contexts&quot;&gt;Combine multiple build contexts&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Buildx&lt;/code&gt; can deal with multiple build contexts as well. For example,
&lt;code&gt;docker.tutorial&lt;/code&gt; is a monorepo that has a configuration file for
packages at the root directory level as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;.
+-- docker.tutorials
|   +-- dockerfiles
|       +-- greeting
|       +-- calculator
|   +-- workspaces
|       +-- greeting
|       +-- calculator
|   +-- package.json
|   +-- tsconfig.json
|   +-- README.md
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It would be good to copy &lt;code&gt;package.json&lt;/code&gt; file only through the build
context flag rather than copying the whole directory to have the
configuration file in the image.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
    --build-context repo=. \
    --build-context app=workspaces/greeting \
    -t &lt;span class=&quot;hljs-variable&quot;&gt;${IMG_NAME}&lt;/span&gt; \
    .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/local-directory/build_from_root.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; node:&lt;span class=&quot;hljs-number&quot;&gt;14.17&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;-alpine AS sourceStage
&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; /&lt;span class=&quot;hljs-built_in&quot;&gt;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --from=repo [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;./package.json&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/source&amp;quot;&lt;/span&gt;]&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --from=repo [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;./tsconfig.json&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/source&amp;quot;&lt;/span&gt;]&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --from=app [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;./&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/source/workspaces/greeting&amp;quot;&lt;/span&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/build-contexts/local-directory/Dockerfile&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;load-build-context-via-absolute-file-path&quot;&gt;Load build context via absolute file path&lt;/h3&gt;
&lt;p&gt;If the build context is not in the same directory as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;.
+-- resources
|   +-- icons
+-- docker.tutorials
|   +-- dockerfiles
|       +-- greeting
|       +-- calculator
|   +-- workspaces
|       +-- greeting
|       +-- calculator
|   +-- package.json
|   +-- README.md
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The absolute file path could be fit in this case:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
  --build-context resources=/Users/Documents/resources/icons \
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/local-directory/build_from_absolute_path.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note: Please do not use &lt;code&gt;tilde(~)&lt;/code&gt; in the file path. &lt;code&gt;Buildx&lt;/code&gt; cannot
find the build context in this form.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Alternatively, the build context can be accessed by notating double-dot(&lt;code&gt;..&lt;/code&gt;) when
the directory is in the parent folder of the current location:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
   --build-context resources=../resources/icons \
   -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt; \
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/local-directory/build_from_parent.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;load-build-context-from-a-git-repository&quot;&gt;Load build context from a Git repository&lt;/h2&gt;
&lt;h3 id=&quot;clone-the-git-repository-via-https&quot;&gt;Clone the git repository via HTTPS&lt;/h3&gt;
&lt;p&gt;It is quite simple to load build context from a Git repository by
specifying the URL of the repository and tagging the branch name with
hash(&lt;code&gt;#&lt;/code&gt;) at the end of the URL as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
  --build-context repo=https://github.com/OttoHung/docker.tutorial.git&lt;span class=&quot;hljs-comment&quot;&gt;#main \&lt;/span&gt;
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/git/https/build_from_public.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By this way, the build context will be cloned to a directory whose name
is as same as the repository in the &lt;code&gt;WORKDIR&lt;/code&gt;. For example, the name of
the repository is &lt;code&gt;docker.tutorials&lt;/code&gt; then the build context will be
stored in a directory named &lt;code&gt;docker.tutorials&lt;/code&gt; as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;code&gt;&lt;div&gt;.
+-- ${WORK_DIR}
|   +-- docker.tutorials
|       +-- README.md
|       +-- node_modules
|       +-- LICENSE
+-- bin
+-- usr
&lt;/div&gt;&lt;/code&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the &lt;code&gt;Dockerfile&lt;/code&gt;, using &lt;code&gt;COPY --from=${buildContextName}&lt;/code&gt; to copy
the build context from the temporary directory into a work directory
as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-comment&quot;&gt;## Stage name is not compulsory if it is not a multi-stage build&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;## But `FROM` instruction must be provided.&lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;## Learn more from https://docs.docker.com/engine/reference/builder/#from&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; node:&lt;span class=&quot;hljs-number&quot;&gt;14.17&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;-alpine AS sourceStage
&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; /&lt;span class=&quot;hljs-built_in&quot;&gt;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --from=repo [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;./&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/source&amp;quot;&lt;/span&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/build-contexts/git/https/public/Dockerfile&quot;&gt;Learn more&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, &lt;code&gt;Buildx&lt;/code&gt; cannot clone a private repository when the access is
unauthenticated. An error message is returned as
&lt;code&gt;fatal: could not read Username for &#39;https://github.com&#39;: terminal prompts disabled&lt;/code&gt;. [&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/git/https/build_from_private.sh&quot;&gt;Learn More&lt;/a&gt;] It looks like &lt;code&gt;Buildx&lt;/code&gt; clones the repository before
executing instructions and there is no other way to provide access
tokens to &lt;code&gt;Buildx&lt;/code&gt; currently.&lt;/p&gt;
&lt;p&gt;The solution for this circumstance could use
&lt;code&gt;--secret&lt;/code&gt; to pass Personal Access Token(PAT) to &lt;code&gt;Buildx&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;pat=&lt;span class=&quot;hljs-variable&quot;&gt;${PAT}&lt;/span&gt; \
docker buildx build \
   --secret id=pat \
   -t &lt;span class=&quot;hljs-variable&quot;&gt;${IMG_NAME}&lt;/span&gt; \
   .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/git/https/build_from_private.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then using &lt;code&gt;RUN&lt;/code&gt; instruction to clone the remote repository which is
much safer than embedded the PAT in the URL in the command line.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --mount=&lt;span class=&quot;hljs-built_in&quot;&gt;type&lt;/span&gt;=secret,id=&lt;span class=&quot;hljs-variable&quot;&gt;${SECRET_ID}&lt;/span&gt; \
    PAT=$(cat /run/secrets/&lt;span class=&quot;hljs-variable&quot;&gt;${SECRET_ID}&lt;/span&gt;) \
    git &lt;span class=&quot;hljs-built_in&quot;&gt;clone&lt;/span&gt; https://&lt;span class=&quot;hljs-variable&quot;&gt;${PAT}&lt;/span&gt;@&lt;span class=&quot;hljs-variable&quot;&gt;${REPO_URL}&lt;/span&gt;.git&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/git/https/private/Dockerfile&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;clone-the-git-repository-via-ssh&quot;&gt;Clone the git repository via SSH&lt;/h3&gt;
&lt;p&gt;By assigning a SSH URL to &lt;code&gt;Buildx&lt;/code&gt; like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
  --build-context repo=git@github.com:OttoHung/docker.tutorials.git&lt;span class=&quot;hljs-comment&quot;&gt;#main \&lt;/span&gt;
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/git/ssh/build.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, the remote repository cannot be cloned and an error message
returned as
&lt;code&gt;unsupported context source **git@github.com** for ${BUILD_CONTEXT_NAME}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To resolve this issue, it is recommended to use &lt;code&gt;--ssh&lt;/code&gt; and &lt;code&gt;RUN&lt;/code&gt;
instruction with &lt;code&gt;Buildx&lt;/code&gt; to clone the repository as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
   --secret id=npm,src=&lt;span class=&quot;hljs-variable&quot;&gt;$HOME&lt;/span&gt;/.npmrc \
   --ssh default=&lt;span class=&quot;hljs-variable&quot;&gt;$SSH_AUTH_SOCK&lt;/span&gt; \
   -t &lt;span class=&quot;hljs-variable&quot;&gt;${IMG_NAME}&lt;/span&gt; \
   .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/git/ssh/build.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; node:&lt;span class=&quot;hljs-number&quot;&gt;14.17&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;-alpine AS sourceStage
&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; /&lt;span class=&quot;hljs-built_in&quot;&gt;source&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;## node-alpine doesn&amp;#x27;t include openssh-client and git by default&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; apk update &amp;amp;&amp;amp; apk upgrade \
    &amp;amp;&amp;amp; apk add openssh-client git&lt;/span&gt;

&lt;span class=&quot;hljs-comment&quot;&gt;## To store SSH key temporarily&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; mkdir -p -m 0700 ~/.ssh \
    &amp;amp;&amp;amp; ssh-keyscan -H &lt;span class=&quot;hljs-variable&quot;&gt;${HOSTING}&lt;/span&gt; &amp;gt;&amp;gt; ~/.ssh/known_hosts&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --mount=&lt;span class=&quot;hljs-built_in&quot;&gt;type&lt;/span&gt;=ssh git &lt;span class=&quot;hljs-built_in&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;${REPO}&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/git/ssh/Dockerfile&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then the build context will be cloned into the same folder structure listed
at &lt;a href=&quot;#clone-the-git-repository-via-https&quot;&gt;Clone the git repository via HTTPS&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;load-build-context-from-a-tarball-via-http-url&quot;&gt;Load build context from a tarball via HTTP URL&lt;/h2&gt;
&lt;p&gt;Build context flag also supports downloading tarball(&lt;code&gt;*.tar&lt;/code&gt; or &lt;code&gt;*.tar.gz&lt;/code&gt;)
via an HTTP URL as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build \
  --build-context dockerTutorial=https://github.com/OttoHung/docker.tutorials/archive/refs/tags/tarball.tar.gz \
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/tarball/build_from_http.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Once the tarball file has been downloaded, it is required to unpack tarball
before copying the contents to another work directory. On macOS, &lt;code&gt;tar -xzf&lt;/code&gt;
could be used to unpack the tarball.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; node:&lt;span class=&quot;hljs-number&quot;&gt;14.17&lt;/span&gt;.&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;-alpine as sourceStage
&lt;span class=&quot;hljs-keyword&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; /&lt;span class=&quot;hljs-built_in&quot;&gt;source&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;ARG&lt;/span&gt; TARBALL_NAME

&lt;span class=&quot;hljs-comment&quot;&gt;## tarball must be downloaded by COPY instruction then be unarchived &lt;/span&gt;
&lt;span class=&quot;hljs-comment&quot;&gt;## by tar command&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;COPY&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; --from=tarball [&lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;./&amp;quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&amp;quot;/source&amp;quot;&lt;/span&gt;]&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;RUN&lt;/span&gt;&lt;span class=&quot;bash&quot;&gt; tar -xzf &lt;span class=&quot;hljs-variable&quot;&gt;${TARBALL_NAME}&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/build-contexts/tarball/Dockerfile&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is recommended to double-check the directory name is as same as the
tarball name or not before making a tarball. If the names of both are
different, such as the tarball packed by GitHub Release, the folder
name must be given to the &lt;code&gt;Dockerfile&lt;/code&gt; to copy the contents because
the tarball name is not the same.&lt;/p&gt;
&lt;h2 id=&quot;load-build-context-from-a-docker-image&quot;&gt;Load build context from a docker image&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Dockerfile 1.4&lt;/code&gt; supports that the docker image can be loaded by &lt;code&gt;FROM&lt;/code&gt;
instruction with the URL of the image as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; https://ghcr.io/OttoHung/greeting:latest
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or specify the name of the docker image:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; alpine:&lt;span class=&quot;hljs-number&quot;&gt;3.15&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/build-contexts/docker-image/Dockerfile&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the command prompt, the docker image must
go with &lt;code&gt;docker-image://&lt;/code&gt; prefix to tell what docker image to load.
For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build
  --build-context image=docker-image://alpine:3.15 \
  -t &lt;span class=&quot;hljs-variable&quot;&gt;${imageName}&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;${tag}&lt;/span&gt; \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/docker-image/build_from_latest.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then using &lt;code&gt;FROM&lt;/code&gt; instruction to import the image:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;FROM&lt;/span&gt; image AS sourceStage
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/dockerfiles/build-contexts/docker-image/Dockerfile&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also, an image digest following up on the tag of the image can be used to specify
a particular version for the image as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;&lt;div&gt;docker buildx build
  --build-context image=docker-image://ghcr.io/ottohung/docker.tutorials:git-https@sha256:b9f33235036f68d3d510a8800e27e3b6514142119cbd5f4862f0506d8cc8552d \
  -t ${imageName}:${tag} \
  .
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/OttoHung/docker.tutorials/blob/main/scripts/build-contexts/docker-image/build_from_version.sh&quot;&gt;Learn More&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Build Context flag is also a convenient way to specify other docker images for
the build, such as base image and image for app, from command prompt dynamically.
In this way, it&#39;s easy to change the base images without modifying &lt;code&gt;Dockerfile&lt;/code&gt;
and it&#39;s not necessary to write multiple &lt;code&gt;Dockerfile&lt;/code&gt; for different platforms.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;div&gt;docker buildx build
  --build-context baseImage=docker-image://alpine:3.15 \
  --build-context appImage=docker-image://node:14.17.1-alpine \
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;reference&quot;&gt;Reference&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/develop/develop-images/dockerfile_best-practices/&quot;&gt;Best practices for writing Dockerfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/buildx_build/#build-context&quot;&gt;Build context&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/develop/develop-images/build_enhancements/#new-docker-build-secret-information&quot;&gt;Build images with BuildKit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/reference/builder/&quot;&gt;Dockerfile Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.docker.com/blog/dockerfiles-now-support-multiple-build-contexts/&quot;&gt;Dockerfiles now Support Multiple Build Contexts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/engine/reference/commandline/build/&quot;&gt;Docker build&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

        &lt;script async src=&quot;https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.js&quot;&gt;&lt;/script&gt;
        
    &lt;/body&gt;
    &lt;/html&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/3745980830145226929/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2022/08/build-docker-image-from-multiple-build.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3745980830145226929'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3745980830145226929'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2022/08/build-docker-image-from-multiple-build.html' title='Build docker image from multiple build contexts'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-7553452308009740255</id><published>2021-03-28T21:23:00.010+10:00</published><updated>2024-11-14T11:21:28.679+10:00</updated><title type='text'>How to use Markdown in Blogger</title><content type='html'>Markdown becomes the most popular documenting language in any technical documentation nowadays. The benefit of using Markdown is getting formatted and highlighted sentences in the short typing. However, Blogger doesn&#39;t support Markdown natively at the time going. In order to use Markdown in Blogger, I googled it online and found there is a useful framework built by `cs905s` on &lt;a href=&quot;https://github.com/cs905s/md-in-blogger&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;https://github.com/cs905s/md-in-blogger&lt;/a&gt;. In this post, I will list down how to implement this and a sample to show if the Markdown still working on this post.

The following way works on my Blogger as you see on this post. If it doesn&#39;t work on your Blogger, please feel free to leave a comment or visit &lt;a href=&quot;https://github.com/cs905s/md-in-blogger&quot; target=&quot;_blank&quot; rel=&quot;nofollow&quot;&gt;https://github.com/cs905s/md-in-blogger&lt;/a&gt;.

&lt;pre class=&quot;markdown&quot;&gt;1. Go to Theme
1. Click Customise -&amp;gt; Edit HTML
1. Paste the following code before `&amp;lt;/head&amp;gt;` 
```html
&amp;lt;link href=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/default.min.css&quot; rel=&quot;stylesheet&quot;&amp;gt;&amp;lt;/link&amp;gt;
```
1. Paste the following code before `&amp;lt;/html&amp;gt;`
```html
&amp;lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/highlight.min.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/showdown/1.6.2/showdown.min.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;//mxp22.surge.sh/markdown-highlight-in-blogger.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
```

Once you have configured the template, you can use Markdown in `HTML view` by click `&amp;lt;&amp;gt;` at left hand side in the toolbox. However, it doesn&#39;t work in the `Compose view`. So please use `Preview` to see the result of rendering.

&amp;gt; Note: &amp;lt; and &amp;gt; are the preserved characters in HTML, please use &amp;amp; lt; and &amp;amp; gt; in your markdown.


In your each post, you just type markdown in the following section to render Markdown:
```html
&amp;lt;pre class=&quot;markdown&quot;&amp;gt;
&amp;lt;/pre&amp;gt;
```

---
----- Mark Down Sample as follows -------
# This is header

# Unordered List
- List 1
  - List 1-1
- List 2

# Ordered list
1. Number 1
  1.1. Number 1.1
  1.1. Number 1.2
1. Number 2

# Table
| To Left | Centre | To Right |
|:--------|:------:|---------:|
|(1,1)    | (1,2)  | (1,3)    |
|(2,1)    | (2,2)  | (2,3)    |

# Mermaid (Not supported Yet)
```mermaid
graph LR
A[Square Rect] -- Link text --&amp;gt; B((Circle))
A --&amp;gt; C(Round Rect)
B --&amp;gt; D{Rhombus}
C --&amp;gt; D
```

# Reference
-  https://github.com/cs905s/md-in-blogger
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/7553452308009740255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2021/03/how-to-use-markdown-in-blogger.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/7553452308009740255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/7553452308009740255'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2021/03/how-to-use-markdown-in-blogger.html' title='How to use Markdown in Blogger'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-4027167955834785950</id><published>2019-06-23T16:14:00.001+10:00</published><updated>2019-06-23T16:25:37.626+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Activation"/><category scheme="http://www.blogger.com/atom/ns#" term="Katalon"/><title type='text'>[Katalon] How to activate Katalon Studio</title><content type='html'>After the Katalon Studio has been installed by the instruction of&amp;nbsp;&lt;a href=&quot;https://totsi04.blogspot.com/2019/06/katalon-how-to-install-katalon-studio.html&quot; target=&quot;_blank&quot;&gt;[Katalon] How to install Katalon Studio&lt;/a&gt;, we have to activate Katalon Studio before using it.&lt;br /&gt;
&lt;br /&gt;
The steps of activation are very simple as well as follows:&lt;br /&gt;
&amp;nbsp; 1. Open the Katalon Studio&lt;br /&gt;
&amp;nbsp; 2. Fill your registered Email and Password to activate Katalon Studio, then click &quot;activate&quot; button.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRksozgOhwPb4wICT-0KlOFqry1fGn-WqtDiF6R4yuBbB6W7EZLM62VxNEPbMpqFJ8a3ncPgyYZyswPOTAWG3IIuYE5HuahO0WJKyFY7pNhRr_bhq0FFH6UaEsZmv1jRHToFvS8R7hqPU/s1600/activation+dialog.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;231&quot; data-original-width=&quot;486&quot; height=&quot;152&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRksozgOhwPb4wICT-0KlOFqry1fGn-WqtDiF6R4yuBbB6W7EZLM62VxNEPbMpqFJ8a3ncPgyYZyswPOTAWG3IIuYE5HuahO0WJKyFY7pNhRr_bhq0FFH6UaEsZmv1jRHToFvS8R7hqPU/s320/activation+dialog.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; 3. Have fun with Katalon Studio&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi37VpW_adOr337p00aYva-jWonHvlgon6idczJEKVX0eCAk0Pb-2Q1zQ_c1FTBxfKvO299SiTyKRD0Bbob-aewdaDKBkwUCnWJbwAxO0JeuhJMlGOquNkmi0Vs0wkCRuX8zdkIvpedh14/s1600/Katalon+IDE.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;744&quot; data-original-width=&quot;1360&quot; height=&quot;175&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi37VpW_adOr337p00aYva-jWonHvlgon6idczJEKVX0eCAk0Pb-2Q1zQ_c1FTBxfKvO299SiTyKRD0Bbob-aewdaDKBkwUCnWJbwAxO0JeuhJMlGOquNkmi0Vs0wkCRuX8zdkIvpedh14/s320/Katalon+IDE.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
Is it easy, right? Let&#39;s do some practice for test cases in the next section.&lt;br /&gt;
&lt;br /&gt;
Next: [Katalon] How to create a test case by using Record &amp;amp; Playback&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/4027167955834785950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/06/katalon-how-to-activate-katalon-studio.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4027167955834785950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4027167955834785950'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/06/katalon-how-to-activate-katalon-studio.html' title='[Katalon] How to activate Katalon Studio'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRksozgOhwPb4wICT-0KlOFqry1fGn-WqtDiF6R4yuBbB6W7EZLM62VxNEPbMpqFJ8a3ncPgyYZyswPOTAWG3IIuYE5HuahO0WJKyFY7pNhRr_bhq0FFH6UaEsZmv1jRHToFvS8R7hqPU/s72-c/activation+dialog.png" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-3678443236707273908</id><published>2019-06-23T15:53:00.000+10:00</published><updated>2019-06-23T16:14:57.807+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Katalon"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>[Katalon] How to install Katalon Studio</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;span style=&quot;font-size: x-small;&quot;&gt;Note: The screenshot may differ than the actual web pages if Katalon updates their official website. (Date of the screenshot is 06/2019)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Katalon Studio is a free automation testing solution built on top of the automation frameworks Selenium, Appium with a particular IDE for API, web app and mobile app testing. By using Katalon, Git, JIRA, Slack, Jenkins, can be integrated into the automation testing flow work.&lt;/div&gt;
&lt;br /&gt;
Let&#39;s learn how to install Katalon Studio in the few steps in an easy way:&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; 1. Go to the home page of Katalon at&amp;nbsp;&lt;a href=&quot;https://www.katalon.com/&quot;&gt;https://www.katalon.com/&lt;/a&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; 2. Click the &quot;Download Now&quot; button&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg42d9D6_WSvPizwa6g7uv3hXqfH_K4ey-Rt9KWvrQNqBS7OsiqC6hT-qiZQbUiygaoVkNLu6g6ronem1XuXCvTvrw3sJ2nGPR_IfsRF9ABYvTK3c2dHndv0rXpL56tGgty3KoEczn97W4/s1600/Download+Katalon+Studio.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;700&quot; data-original-width=&quot;1348&quot; height=&quot;166&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg42d9D6_WSvPizwa6g7uv3hXqfH_K4ey-Rt9KWvrQNqBS7OsiqC6hT-qiZQbUiygaoVkNLu6g6ronem1XuXCvTvrw3sJ2nGPR_IfsRF9ABYvTK3c2dHndv0rXpL56tGgty3KoEczn97W4/s320/Download+Katalon+Studio.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; 3. Create an account for activating Katalon Studio and upload the testing report to Katalon Analysis.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVePOTCfGjnRxcW6lTp77d7vmzgpdXaalJK0fxtwDmcJ5uj8kijfhdbW5QJk6a5jEU_gGwuVVrRNmGe2h_3YXm5aAwn7cPLEaEr02kR3i-v4bEC9b8-MMC_PBP1lE7Zc1JuH9TFixvnYY/s1600/Sign+up+to+activate+Katalon+Studio.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;701&quot; data-original-width=&quot;1350&quot; height=&quot;166&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVePOTCfGjnRxcW6lTp77d7vmzgpdXaalJK0fxtwDmcJ5uj8kijfhdbW5QJk6a5jEU_gGwuVVrRNmGe2h_3YXm5aAwn7cPLEaEr02kR3i-v4bEC9b8-MMC_PBP1lE7Zc1JuH9TFixvnYY/s320/Sign+up+to+activate+Katalon+Studio.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; 4. The downloading progress of installation file according to your operating system will be started automatically. If it does not, just choose the platform from the dropdown list and click the &quot;Download&quot; button.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYx2jAvZb8l2S8Z-qvXtJCGqWla16BcoHuz9PjONj8lhbkcDN0ROFGbglY74MTGLgEiXKdsZSMxWN17mRyDXfeE-FHlThoUMzwlM9B8yjkBwwhfdg15jiQ2WJZcxolEiy2JDyvXmUP3s0/s1600/Choose+platform+and+dowlonad.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;583&quot; data-original-width=&quot;1344&quot; height=&quot;138&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYx2jAvZb8l2S8Z-qvXtJCGqWla16BcoHuz9PjONj8lhbkcDN0ROFGbglY74MTGLgEiXKdsZSMxWN17mRyDXfeE-FHlThoUMzwlM9B8yjkBwwhfdg15jiQ2WJZcxolEiy2JDyvXmUP3s0/s320/Choose+platform+and+dowlonad.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
After the installation finished, we can start to &quot;activate&quot; Katalon Studio for further tutorials.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Next: &lt;a href=&quot;https://totsi04.blogspot.com/2019/06/katalon-how-to-activate-katalon-studio.html&quot;&gt;[Katalon] How to activate Katalon Studio&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/3678443236707273908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/06/katalon-how-to-install-katalon-studio.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3678443236707273908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3678443236707273908'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/06/katalon-how-to-install-katalon-studio.html' title='[Katalon] How to install Katalon Studio'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg42d9D6_WSvPizwa6g7uv3hXqfH_K4ey-Rt9KWvrQNqBS7OsiqC6hT-qiZQbUiygaoVkNLu6g6ronem1XuXCvTvrw3sJ2nGPR_IfsRF9ABYvTK3c2dHndv0rXpL56tGgty3KoEczn97W4/s72-c/Download+Katalon+Studio.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-4862802794913315145</id><published>2019-05-18T11:02:00.001+10:00</published><updated>2019-05-18T11:06:13.751+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="GCP"/><title type='text'>[GCP] How to fix &quot;Permissions error fetching application.. &quot; while deploying a service to an existing project</title><content type='html'>&lt;pre class=&quot;markdown&quot;&gt;It&#39;s simple to fix this problem by the following steps:

1. use `gcloud config list` to see the setting of the current project.

2. If the `project` field is used with the project name, using &quot;PROJECT-ID&quot; instead by `gcloud config set project {{ PROJECT-ID }}`.

3. run `gcloud app deploy` again, this problem will be resolved.



# Reference

&lt;a href=&quot;https://stackoverflow.com/questions/49785578/gcloud-app-deploy-error-permissions-error-fetching-application-apps-project-n&quot;&gt;gcloud app deploy ERROR: Permissions error fetching application [apps/&lt;project_name&gt;]&lt;/project_name&gt;&lt;/a&gt;
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/4862802794913315145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/05/gcp-how-to-fix-permissions-error.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4862802794913315145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4862802794913315145'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/05/gcp-how-to-fix-permissions-error.html' title='[GCP] How to fix &quot;Permissions error fetching application.. &quot; while deploying a service to an existing project'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-929608868441947825</id><published>2019-02-12T22:17:00.001+10:00</published><updated>2019-02-27T20:47:42.705+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Tutorial"/><category scheme="http://www.blogger.com/atom/ns#" term="Twig"/><title type='text'>[Tutorial] How to use variables in Twig</title><content type='html'>&lt;pre class=&quot;markdown&quot;&gt;The tools used in this tutorial are as following:
|Spec        | Version      |
|:------------:|--------------|
|OS          | MacOS 10.14.3|
|PHP         | &amp;gt;= 7.0    |
|Twig        | 2.x          |

Note. This post is written in Markdown language which has not been supported in Blogger for mobile browser yet . Please read this article by a desktop computer for a better experience.

# Introduction
Like other languages, Twig has variables and expressions for developers and designers to implement user interface template. In this section, let&#39;s see how to use variables in Twig.


# How to do
It&#39;s simple to write a variable in Twig as in PHP. 
```twig
{# if name is kitty by setting #}
  name
```


However, it will be printed as plain text in the webpage if we write a variable as above. 
```
name
```


In order to print the value of the variable, a pair of curly braces have to be used to enclose the variable.
```twig
  {# if name is kitty by setting #}
  {{ name }}
```
&lt;br&gt;
Then Twig template engine will print it on the webpage.
```
kitty
```
&lt;br&gt;
The variables are also able to be manipulated in the control structure:
```twig
 {% set name = &#39;kitty&#39; %}

 {% if name is not empty %}
   {% set greeting = &quot;Hello &quot; ~ name %}
 {% else %}
   {% set greeting = &quot;Hellow Anonymous&quot; %}
 {% endif %}

 {{ greeting }}
```
&lt;br&gt;
The result is:
```
Hello kitty
```
&lt;br&gt;
If the variable is an object, the attributes(properties) of a variable can be accessed by a dot symbol(.).
```twig
  house.door
```
&lt;br&gt;
The attributes of a variable are also able to be accessed by &quot;subscript&quot; syntax. However, it doesn&#39;t work for the attributes which have special characters, such as &#39;-&#39;, in the name.
```twig
  house[&#39;door&#39;]
```
&lt;br&gt;
In order to let designer and developer access attributes which have special characters in the name, Twig provides `attribute()` for designer and developer to access attributes.
```twig
  attribute(house, &#39;data-door&#39;)
```
&lt;br&gt;
A null will be returned if a variable or attribute does not exist when the `strict_variables` option is set to false, otherwise, Twig will throw an error.
&lt;br&gt;
The convenient thing is multiple variables can be assigned values at the same time in one line:
```twig
{% set door, room = 4, 2 %}
```
It is equivalent to:
```twig
{% set door = 4 %}
{% set room = 2 %}
```


# Practice
Let&#39;s do some practice. The JSON object for practice is as follows:
```json
{
  &quot;houses&quot;:[
      {
          &quot;name&quot;: &quot;1 storey house&quot;,
          &quot;door&quot;: 4,
          &quot;window&quot;: 4,
          &quot;room&quot;: 4
      },
      {
          &quot;name&quot;: &quot;2 storey house&quot;,          
          &quot;door&quot;: 4,
          &quot;window&quot;: 4,
          &quot;room&quot;: 2
      }
  ]
}
```
&lt;br&gt;
Let&#39;s print the details of houses:
```twig
{% for house in houses %}
  {{ house.door }} doors in {{ house.name }}
{% endfor %}
```
&lt;br&gt;
The result will be:
```
4 doors in 1 storey house
4 doors in 2 storey house
```


# Setting Variables
The variables can be set a value, such as string, integer, floating number, array, and key-value pairs, by Control Structure in a variant way.


## Set a string to a variable
```twig
{% set var = &#39;this is a string&#39; %}

{# Tests the result #}
{{ var }}
```


The result will be
```
this is a string
```
&lt;br&gt;
## Set an integer to a variable
```twig
{% set var = 15 %}

{# Tests the result #}
{{ var }}
```
&lt;br&gt;
The result will be
```
15
```
&lt;br&gt;
## Set a floating number to a variable
```twig
{% set var = 12.33456 %}

{# Tests the result #}
{{ var }}
```
&lt;br&gt;
The result will be
```
12.33456
```
&lt;br&gt;
## Set a string array to a variable
```twig
{% set string_array = [&#39;one&#39;, &#39;two&#39;, &#39;three&#39;, &#39;four&#39;] %}
&lt;br&gt;
{# Tests the result #}
{% for str in string_array %}
{{ str }}
{% endfor %}
```
&lt;br&gt;
The result will be
```
one
two
three
four
```
&lt;br&gt;
## Set an integer array to a variable
```twig
{% set integer_array = [1, 2, 3, 4] %}

{# Tests the result #}
{% for int in integer_array %}
{{ int }}
{% endfor %}
```
&lt;br&gt;
The result will be
```
1
2
3
4
```
&lt;br&gt;
## Set a floating number array to a variable
```twig
{% set float_array = [1.1, 2.2, 3.3, 4.4] %}
&lt;br&gt;
{# Tests the result #}
{% for float in float_array %}
{{ float }}
{% endfor %}
```
&lt;br&gt;
The result will be
```
1.1
2.2
3.3
4.4
```
&lt;br&gt;
## Set key-value pairs to a variable, and the key is string
```twig
{% set map_str_key = {&#39;one&#39;: &#39;first&#39;, &#39;two&#39;: &#39;second&#39;, &#39;three&#39;: &#39;third&#39;} %}

{# Tests the result #}
{% for key, value in map_str_key %}
[{{ key }}] = {{ value }}
{% endfor %}
```
&lt;br&gt;
The result will be
```
[one] = first
[two] = second
[three] = third
```
&lt;br&gt;
## Set key-value pairs to a variable, and the key is integer
```twig
{% set map_int_key = {1: &#39;first&#39;, 2: &#39;second&#39;, 3: &#39;third&#39;} %}

{# Tests the result #}
{% for key, value in map_int_key %}
[{{ key }}] = {{ value }}
{% endfor %}
```
&lt;br&gt;
The result will be
```
[1] = first
[2] = second
[3] = third
```
&lt;br&gt;
If we store key as an integer, we can use square brackets(`[]`) to manipulate this variable:
```twig
{# this will throw an error
[0] = {{ map_int_key[0] }}
#}
&lt;br&gt;
[1] = {{ map_int_key[1] }}
[2] = {{ map_int_key[2] }}
[3] = {{ map_int_key[3] }}
```
&lt;br&gt;
The result is:
```
[1] = first
[2] = second
[3] = third
```
&lt;br&gt;
When we use this approach to manipulate the variable, we must be careful that does not access the key which doesn&#39;t exist. Otherwise, an error will be thrown. 
&lt;br&gt;
## Set a block of value to the variable
The `set tag` not only accepts a line of value but also accepts a multiple lines value. Let&#39;s see how to implement it.
If we want to use a set block to set value, the value should be enclosed by `{%set ... %}` and `{% endset %}`.
```twig
{% set integer_array = [1,2,3,4] %}

{% set ints %}
&amp;lt;ol&amp;gt;
 {% for int in integer_array %}
   &amp;lt;il&amp;gt;{{ int }}&amp;lt;/il&amp;gt;
 {% endfor %}
&amp;lt;/ol&amp;gt;
{% endset %}

{# Shows the result #}
{{ ints }}
```
&lt;br&gt;
The result is 
```html
&amp;lt;ol&amp;gt;
  &amp;lt;il&amp;gt;1&amp;lt;/il&amp;gt;
  &amp;lt;il&amp;gt;2&amp;lt;/il&amp;gt;
  &amp;lt;il&amp;gt;3&amp;lt;/il&amp;gt;
  &amp;lt;il&amp;gt;4&amp;lt;/il&amp;gt;
&amp;lt;/ol&amp;gt;
```
&lt;br&gt;
However, the `{% set ... %} ... {% endset %}` code block doesn&#39;t convert JSON string into an object and it cannot be used to assign key-value pairs:
```twig
{% set home %}
{
  &#39;door&#39;: 4,
  &#39;room&#39;: 2,
  &#39;toilet&#39;: 1
}
{% endset %}

{# Shows the result #}
{{ home }}

{# this doesn&#39;t show anything #}
{% for item in home %}
{{ item }}
{% endfor %}

{# this will throw error #}
{{ home[&#39;door&#39;] }}
```
&lt;br&gt;
The result is:
```
{
  &#39;door&#39;: 4,
  &#39;room&#39;: 2,
  &#39;toilet&#39;: 1
}
```
&lt;br&gt;
As a result, the `{% set ... %} ... {% endset %}` code block only treats the value as text as the demonstration in the [official document](https://twig.symfony.com/doc/2.x/tags/set.html). If we use HTML tags assigned to the variables in this sort of code block and automatic output escaping is enabled, the HTML tags will be encoded to make sure the content is safe.
```twig
{% set trh = &#39;&amp;lt;tr&amp;gt;&#39; %}
{% set tre = &#39;&amp;lt;/tr&amp;gt;&#39; %}
{% set tdh = &#39;&amp;lt;td&amp;gt;&#39; %}
{% set tde = &#39;&amp;lt;/td&amp;gt;&#39; %}

{% set table %}
&amp;lt;table&amp;gt;
  {{ trh }}
      {{ tdh }} cell 1 {{ tde }}
      {{ tdh }} cell 2 {{ tde }}
      {{ tdh }} cell 3 {{ tde }}
  {{ trh }}
  {{ trh }}
      {{ tdh }} cell 4 {{ tde }}
      {{ tdh }} cell 5 {{ tde }}
      {{ tdh }} cell 6 {{ tde }}
  {{ trh }}
&amp;lt;/table&amp;gt;
{% endset %}

{# shows the result #}
{{ table }}
```
&lt;br&gt;
The result will be:
```html
&amp;lt;table&amp;gt;
        &amp;amp;lt;tr&amp;amp;gt;
                &amp;amp;lt;td&amp;amp;gt; cell 1 &amp;amp;lt;/tr&amp;amp;gt;
                &amp;amp;lt;td&amp;gamp;t; cell 2 &amp;amp;lt;/tr&amp;amp;gt;
                &amp;amp;lt;td&amp;amp;gt; cell 3 &amp;amp;lt;/tr&amp;amp;gt;
        &amp;amp;lt;tr&amp;amp;gt;
        &amp;amp;lt;tr&amp;amp;gt;
                &amp;amp;lt;td&amp;amp;gt; cell 4 &amp;amp;lt;/tr&amp;amp;gt;
                &amp;amp;lt;td&amp;amp;gt; cell 5 &amp;amp;lt;/tr&amp;amp;gt;
                &amp;amp;lt;td&amp;amp;gt; cell 6 &amp;amp;lt;/tr&amp;amp;gt;
        &amp;amp;lt;tr&amp;amp;gt;

&amp;lt;table&amp;gt;
```


## Variable Scope
If a variable has been declared inside a `for` loop, it cannot be accessed outside of the loop.
```twig
{% set list=[1,2,3,4,5] %}

{% for i in list %}
 {% set result = i %}
{% endfor %}

{# An error will be thrown #}
{{ result }}
```
&lt;br&gt;
But it can be accessed if it has been declared outside the loop:
```twig
{% set list=[1,2,3,4,5] %}

{% set result = 0 %}

{% for i in list %}
 {% set result = i %}
{% endfor %}

{# The result is 5 #}
{{ result }}
```
&lt;br&gt;
# Filter
A filter can be applied to the variables to trim space, lowercase all of the characters, merge an array and so on.
```twig
{% set name = &#39; Kitty&#39; %}

{# this will print &#39;Kitty&#39; instead of &#39; Kitty&#39; #}
{{ name }}
```
&lt;br&gt;
This will be introduced in the next tutorial.
&lt;br&gt;
# Reference
[Twig Variables](https://twig.symfony.com/doc/2.x/templates.html#variables)
[set Tag](https://twig.symfony.com/doc/2.x/tags/set.html)

## Relevant Readings
[How to setup development environment for Twig on MacOS](https://totsi04.blogspot.com/2019/02/tutorial-how-to-setup-development.html)
&lt;/pre&gt;

</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/929608868441947825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/02/tutorial-how-to-use-variables-in-twig.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/929608868441947825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/929608868441947825'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/02/tutorial-how-to-use-variables-in-twig.html' title='[Tutorial] How to use variables in Twig'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-2890652407795201505</id><published>2019-02-12T19:53:00.001+10:00</published><updated>2019-02-12T19:53:16.735+10:00</updated><title type='text'>Find Window&#39;s Handle through PID</title><content type='html'>&lt;pre class=&quot;markdown&quot;&gt;```cpp
typedef _ProcessHwnd

{

  DWORD ProcessID;
  HWND hwndProcess;

} PROCESSHWND, * PPROCESSHWND;


DWORD GetHWNDForProcess(DWORD ProcessID, PHWND ProcessHWND);
BOOL CALLBACK FindProcessHWNDThruEnum(HWND hwnd, LPARAM lParam);

// example function
// returns 0 if success, results of GetLast Error if not
// ProcessID is the process you are interested in
// ProcessHWND will have the process&#39; associated window handle.
// Or NULL, if the process doesn&#39;t have a window
//
// Usage: GetHWNDForProcess(ProcId, &amp;amp;ProcHWND);
//

DWORD GetHWNDForProcess(DWORD ProcessID, PHWND ProcessHWND)
{
  DWORD ErrValue = 0;
  BOOL fEnumWindows = FALSE;
  PROCESSHWND prochwndFind;

// Initialize the structure
  memset(&amp;amp;prochwndFind, 0, sizeof(prochwndFind));
  prochwndFind.ProcessID = ProcessID;
  fEnumWindows = EnumWindows(FindProcessHWNDThruEnum, (LPARAM) &amp;amp;prochwndFind);

// Make sure EnumWindows succeeded
  if(fEnumWindows){
    *ProcessHWND = prochwndFind.hwndProcess;&lt;/pre&gt;
&lt;pre class=&quot;markdown&quot;&gt;  }else{
   ErrValue = GetLastError();&lt;/pre&gt;
&lt;pre class=&quot;markdown&quot;&gt;  }&lt;/pre&gt;
&lt;pre class=&quot;markdown&quot;&gt;  return ErrValue;
}

// The EnumWindowsProc callback
BOOL CALLBACK FindProcessHWNDThruEnum(HWND hwnd, LPARAM lParam)
{
  PPROCESSHWND prochwndFind;
  DWORD ThisProcessID = 0;
  DWORD ThisThreadID = 0; // For completeness, not needed

  prochwndFind = (PPROCESSHWND) lParam;
  ThisThreadID = GetWindowThreadProcessId(hwnd, &amp;amp;ThisProcessID);

  if(ThisProcessID == prochwndFind.ProcessID)
  {
    prochwndFind.hwndProcess = hwnd);&lt;/pre&gt;
&lt;pre class=&quot;markdown&quot;&gt;    return FALSE;&lt;/pre&gt;
&lt;pre class=&quot;markdown&quot;&gt;  }else{
    return TRUE;&lt;/pre&gt;
&lt;pre class=&quot;markdown&quot;&gt;  }
}
```
&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/2890652407795201505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/02/find-windows-handle-through-pid.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/2890652407795201505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/2890652407795201505'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/02/find-windows-handle-through-pid.html' title='Find Window&#39;s Handle through PID'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-8045555641627064914</id><published>2019-02-10T21:14:00.000+10:00</published><updated>2019-02-12T19:41:38.099+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><category scheme="http://www.blogger.com/atom/ns#" term="Tutorial"/><category scheme="http://www.blogger.com/atom/ns#" term="Twig"/><category scheme="http://www.blogger.com/atom/ns#" term="Twig Packs"/><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio Code"/><category scheme="http://www.blogger.com/atom/ns#" term="Visual Studio Code Extensions"/><title type='text'>[Tutorial] How to setup development environment for Twig on MacOS</title><content type='html'>The tools used in this tutorial are as following:&lt;br /&gt;
&lt;b&gt;OS&amp;nbsp;&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; : MacOS 10.14.3&lt;br /&gt;
&lt;b&gt;PHP version&lt;/b&gt; : &amp;gt;= 7.0&lt;br /&gt;
&lt;b&gt;Twig version&amp;nbsp;&lt;/b&gt;: 2.x&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Introduction&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
Twig is a template engine for the web&amp;nbsp;developers and designers to implement user interface template in PHP by built-in tags, filters, and functions. The benefit of&amp;nbsp;using Twig to implement user interface template is enhancing the readability&amp;nbsp;of code, reducing the complexity of code, and making it be extendable because the templates can be inherited and included in other templates in Twig. It sounds great, right? So, let&#39;s have a try with Twig right now.&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;IDE&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
According to the document from Twig, it shows that there are plenty of editors&amp;nbsp;which are able to be used to implement Twig template. In this case, I chose &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt; as my IDE due to that I can have &lt;a href=&quot;https://www.shopify.com.au/partners/blog/best-visual-studio-code-extensions-2017&quot;&gt;lots of extensions&lt;/a&gt; which helps me backup settings, highlight syntax and provide auto-completion for Twig template. The best thing is it&#39;s fast than&amp;nbsp;Netbeans and Eclipse I used to implement projects in PHP and Java. Also,&amp;nbsp;&lt;a href=&quot;https://twigfiddle.com/&quot;&gt;TwigFiddle&amp;nbsp;&lt;/a&gt;is a very good online Twig template editor which provides varieties of Twig in different version and the template can be saved online. Furthermore, the testing data can be filled to test the Twig template in real-time. Or you can find other IDE and extensions by click &lt;a href=&quot;https://twig.symfony.com/doc/2.x/templates.html&quot;&gt;here&lt;/a&gt;.&lt;/div&gt;
&lt;br /&gt;
To install Twig Packs for VSC, please refer to the following photo:&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwuTmRyTOWHmjxVvJ8hp3ORYxHQhf0f6MHZTncnmU_HE_4xpQaCXOkWYksUqlVjYO6QOP3SG1NDYIY8ec8c2A9N-Fc7DpLGJItyxFZxoQA4DSX9MYvao9OOKHrUyVe2gAm-C6mxm-QxIw/s1600/how+to+install+Twig+Pack+in+VSC.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1079&quot; data-original-width=&quot;1600&quot; height=&quot;215&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwuTmRyTOWHmjxVvJ8hp3ORYxHQhf0f6MHZTncnmU_HE_4xpQaCXOkWYksUqlVjYO6QOP3SG1NDYIY8ec8c2A9N-Fc7DpLGJItyxFZxoQA4DSX9MYvao9OOKHrUyVe2gAm-C6mxm-QxIw/s320/how+to+install+Twig+Pack+in+VSC.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Installation&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
In order to run a Twig template on the local machine, the Twig template engine has to be installed via &lt;a href=&quot;https://getcomposer.org/download/&quot;&gt;Composer&lt;/a&gt;. The command for Twig template engine installation is as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;markdown&quot;&gt;```sh
composer require &quot;twig/twig:^2.0&quot;
```
&lt;/pre&gt;
&lt;br /&gt;
That&#39;s it. It&#39;s simple, right?&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt; &lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Trouble Shooting&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
Q: &lt;b&gt;Where I can find my default PHP?&lt;/b&gt;&lt;br /&gt;
A: Execute&amp;nbsp;&lt;span style=&quot;background-color: #f0f0f0; font-family: &amp;quot;arial&amp;quot;; font-size: 12px;&quot;&gt;&amp;nbsp;which php&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Q: What can I do if &#39;php&amp;nbsp;-version&#39; still shows php v5.x?&lt;br /&gt;
A:&lt;br /&gt;
&lt;pre class=&quot;markdown&quot;&gt;Normally, the default PHP is allocated at `/usr/bin` on macOS. So, just edit your `~/.bash_profile` and insert `export PATH=/usr/bin:$PATH` in this file. After that, just execute `. ~/.bash_profile` to update settings.
&lt;/pre&gt;
&lt;br /&gt;
Q: What can I do if I got Permission Denied when using composer to install Twig? A: By default, composer&amp;nbsp;is installed in /vendor. So, just run the command as follows:&lt;br /&gt;
&lt;pre style=&quot;background: #f0f0f0; border: 1px dashed #cccccc; color: black; font-family: &amp;quot;arial&amp;quot;; font-size: 12px; height: auto; line-height: 20px; overflow: auto; padding: 0px; text-align: left; width: 99%;&quot;&gt;&lt;code style=&quot;color: black; word-wrap: normal;&quot;&gt; sudo chown -R $USER /vendor  
&lt;/code&gt;&lt;/pre&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;a href=&quot;https://twig.symfony.com/&quot;&gt;Twig&lt;/a&gt; &lt;a href=&quot;https://twig.symfony.com/doc/2.x/installation.html&quot;&gt;Install Twig by composer&lt;/a&gt;

&lt;br /&gt;
&lt;h1 class=&quot;grid--cell fs-headline1 fl1 ow-break-word&quot; itemprop=&quot;name&quot; style=&quot;background-color: white; border: 0px; box-sizing: inherit; color: #242729; flex: 1 1 auto !important; font-family: Arial, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, sans-serif; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; font-weight: inherit; line-height: 1.3; margin: 0px 0px 0.5em; overflow-wrap: break-word !important; padding: 0px; vertical-align: baseline;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/41212362/composer-file-put-contents-composer-json-failed-to-open-stream-permission&quot;&gt;Composer: file_put_contents(./composer.json): failed to open stream: Permission denied&lt;/a&gt;&lt;/span&gt;&lt;/h1&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/8045555641627064914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/02/tutorial-how-to-setup-development.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/8045555641627064914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/8045555641627064914'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/02/tutorial-how-to-setup-development.html' title='[Tutorial] How to setup development environment for Twig on MacOS'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwuTmRyTOWHmjxVvJ8hp3ORYxHQhf0f6MHZTncnmU_HE_4xpQaCXOkWYksUqlVjYO6QOP3SG1NDYIY8ec8c2A9N-Fc7DpLGJItyxFZxoQA4DSX9MYvao9OOKHrUyVe2gAm-C6mxm-QxIw/s72-c/how+to+install+Twig+Pack+in+VSC.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-6017618463505238159</id><published>2019-01-08T20:42:00.000+10:00</published><updated>2019-01-08T20:48:47.612+10:00</updated><title type='text'>How to avoid shopping on a fraud website</title><content type='html'>As for the post about the frauds ads on Facebook, I would like to share some basic tricks to let you get rid of the fraud website.&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
1. Domain name is always as same as the brand name.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAatktQ7WGtoL1_cc5wYjidbxz_TXwVrxqjaXy6_JSZmyJtvupvTv4iqAXRGgR64h5toJdyJur9-y-42WpvGqiFb4aw9TZek_9689QeMxgXlMd0OR9GK1cEKXYF8wlTRyt0-uGXAvF0Pg/s1600/Screen+Shot+2019-01-08+at+7.03.35+pm.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;638&quot; data-original-width=&quot;1263&quot; height=&quot;161&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAatktQ7WGtoL1_cc5wYjidbxz_TXwVrxqjaXy6_JSZmyJtvupvTv4iqAXRGgR64h5toJdyJur9-y-42WpvGqiFb4aw9TZek_9689QeMxgXlMd0OR9GK1cEKXYF8wlTRyt0-uGXAvF0Pg/s320/Screen+Shot+2019-01-08+at+7.03.35+pm.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&amp;nbsp;The fraud website cannot use the official domain registered by the brand already. If the website represents the official website, check the domain name first. But read the domain name carefully, some fraud side will use a similar name to cheat you, such as www.leg0.com or www.Iego.com. The best way is to google the name of the shop and sees if Google can find it. Also, check the details what Google shows&amp;nbsp;to you.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXiy2qYHYvywEEHi8cdhq0lKWVbsdlc4Hdjc8hMIZSu8jP_v5nQ02oUilV_zVMqgZfnDGCQan93O5mWdVCJah3L-ihZqQDS6lDrHD7QJQ6muKKPDAjb8M8FcyrXXc34JIwJ8Lbjulo-_g/s1600/Screen+Shot+2019-01-08+at+8.30.09+pm.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;560&quot; data-original-width=&quot;1229&quot; height=&quot;145&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXiy2qYHYvywEEHi8cdhq0lKWVbsdlc4Hdjc8hMIZSu8jP_v5nQ02oUilV_zVMqgZfnDGCQan93O5mWdVCJah3L-ihZqQDS6lDrHD7QJQ6muKKPDAjb8M8FcyrXXc34JIwJ8Lbjulo-_g/s320/Screen+Shot+2019-01-08+at+8.30.09+pm.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
2. The layout(details) of the website&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAatktQ7WGtoL1_cc5wYjidbxz_TXwVrxqjaXy6_JSZmyJtvupvTv4iqAXRGgR64h5toJdyJur9-y-42WpvGqiFb4aw9TZek_9689QeMxgXlMd0OR9GK1cEKXYF8wlTRyt0-uGXAvF0Pg/s1600/Screen+Shot+2019-01-08+at+7.03.35+pm.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;638&quot; data-original-width=&quot;1263&quot; height=&quot;161&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAatktQ7WGtoL1_cc5wYjidbxz_TXwVrxqjaXy6_JSZmyJtvupvTv4iqAXRGgR64h5toJdyJur9-y-42WpvGqiFb4aw9TZek_9689QeMxgXlMd0OR9GK1cEKXYF8wlTRyt0-uGXAvF0Pg/s320/Screen+Shot+2019-01-08+at+7.03.35+pm.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYEu_mBpwAUUB2PoIeMAGWnCpT1r220Yh-EYvZPeCQFU5Z4neuoIrSgsRzR7nZB5Ax0LWRHaTRYWhY3lV2q9OYcmlgbXMSmunUUK_hzN33cYzvwj-5tywTxsvNwEbkFBuVCbEMdNoskYk/s1600/Screen+Shot+2019-01-08+at+7.05.31+pm.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;552&quot; data-original-width=&quot;1266&quot; height=&quot;139&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYEu_mBpwAUUB2PoIeMAGWnCpT1r220Yh-EYvZPeCQFU5Z4neuoIrSgsRzR7nZB5Ax0LWRHaTRYWhY3lV2q9OYcmlgbXMSmunUUK_hzN33cYzvwj-5tywTxsvNwEbkFBuVCbEMdNoskYk/s320/Screen+Shot+2019-01-08+at+7.05.31+pm.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
If the layout of the website is awful or everything mixed together, you should be careful that it must be a fraud website. For instance, this website screenshot the rating, but not to implement it. If you can not see any review on the website, it must be a fraud.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
3. Do not pay by Credit Card or Bank Transfer&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp;The scammers will reuse your card details to make more requests. Pay by PayPal or other organisations which can suspend/hold the payment when you make a dispute is the best choice.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
4. Do more research before you place an order&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp;Use the keyword on the website on Google to see how many people visit this site and interacted with it. Just be careful the fraud review because the scammers are not along.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
If you still cannot make sure that website is a fraud or not, just leave it alone and ignore the popup ads from the social media because it is not worth to pay the money you got by your hard working.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
May the force be with you.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Useful Links: (Before clicking the link below, it&#39;s a good practice to google the title of links for avoiding phishing)&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://www.accc.gov.au/consumers/online-shopping/shopping-online&quot;&gt;Protecting your online shopping rights&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://www.ftc.gov/policy/international/competition-consumer-protection-authorities-worldwide&quot;&gt;Competition &amp;amp; Consumer Protection Authorities Worldwide&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://www.scamwatch.gov.au/types-of-scams/buying-or-selling/online-shopping-scams&quot;&gt;Online Shopping scams&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/6017618463505238159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/01/how-to-prevent-not-to-buy-goods-on.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/6017618463505238159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/6017618463505238159'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/01/how-to-prevent-not-to-buy-goods-on.html' title='How to avoid shopping on a fraud website'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAatktQ7WGtoL1_cc5wYjidbxz_TXwVrxqjaXy6_JSZmyJtvupvTv4iqAXRGgR64h5toJdyJur9-y-42WpvGqiFb4aw9TZek_9689QeMxgXlMd0OR9GK1cEKXYF8wlTRyt0-uGXAvF0Pg/s72-c/Screen+Shot+2019-01-08+at+7.03.35+pm.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-4596538914806185808</id><published>2019-01-08T19:18:00.001+10:00</published><updated>2019-01-08T19:20:28.569+10:00</updated><title type='text'>Beware of the fraud ads on Facebook timeline</title><content type='html'>It&#39;s not about the coding but this can save your pocket. My wife tried to buy a Christmas gift for me from an online shop which pretends as an official Lego website and advertises on Facebook. The website looks like the official one on the mobile, however, it doesn&#39;t do it well for the desktop version.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1DbsVOOl7UPVLkqnrzned8UvoCqDwag4Jk4R6somaQWPwoKFNoIzyReIi5KrfH79XH3DwpU1thXGrfMcuen3kMZPPt_1GPpMyowQFlacBwYjWi5LGQnCqUbFLIVAQGazkUVYfwVrXt-w/s1600/Screen+Shot+2019-01-08+at+7.03.35+pm.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;638&quot; data-original-width=&quot;1263&quot; height=&quot;161&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1DbsVOOl7UPVLkqnrzned8UvoCqDwag4Jk4R6somaQWPwoKFNoIzyReIi5KrfH79XH3DwpU1thXGrfMcuen3kMZPPt_1GPpMyowQFlacBwYjWi5LGQnCqUbFLIVAQGazkUVYfwVrXt-w/s320/Screen+Shot+2019-01-08+at+7.03.35+pm.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
The photo of products looks like the official one. If I don&#39;t open it on my laptop, I won&#39;t find the awful design of this website. So, please check the details, such as the rating, of the product before place&amp;nbsp;an order. The rating on this page is photocopied so that we cannot see the actual review or rating. This shop tries to create more new Facebook accounts and advertise on it, even someone report the fraud ads to Facebook.&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf07doN95rvXSOdZiB6jVSJAD65_IdCYlXhzKICFS_zLOjP8AUX2zk8ayy0g2Ijs1wicDtl0Mi4RBBFlLy7qvawLsW3GC_gWlxeXEpqWKhk0jXZEYwEwoyJgnYbgDq5TQMf_0I_tMZEac/s1600/Screen+Shot+2019-01-08+at+7.05.31+pm.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;552&quot; data-original-width=&quot;1266&quot; height=&quot;139&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf07doN95rvXSOdZiB6jVSJAD65_IdCYlXhzKICFS_zLOjP8AUX2zk8ayy0g2Ijs1wicDtl0Mi4RBBFlLy7qvawLsW3GC_gWlxeXEpqWKhk0jXZEYwEwoyJgnYbgDq5TQMf_0I_tMZEac/s320/Screen+Shot+2019-01-08+at+7.05.31+pm.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
I&#39;m so so sorry for that it makes my wife lose $100. As a result, Do not buy anything from the ads on Facebook to prevent fraud ads. Just Google the name of the shop which you already knew and someone has bought something from it. Or chose the shop which accepts PayPal, then you may have a chance to get your money back if it&#39;s a fraud shop, but you still have to take a risk. In my opinion, the best way is that only buy the stuff from wherever you trust.&lt;/div&gt;
&lt;br /&gt;
By the way, don&#39;t click the ads underneath this post which provided by Google if you don&#39;t know that shop. I trust Google but people make mistake as same as me. Good luck, guys.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/4596538914806185808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2019/01/beware-of-fraud-ads-on-facebook-timeline.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4596538914806185808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4596538914806185808'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2019/01/beware-of-fraud-ads-on-facebook-timeline.html' title='Beware of the fraud ads on Facebook timeline'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1DbsVOOl7UPVLkqnrzned8UvoCqDwag4Jk4R6somaQWPwoKFNoIzyReIi5KrfH79XH3DwpU1thXGrfMcuen3kMZPPt_1GPpMyowQFlacBwYjWi5LGQnCqUbFLIVAQGazkUVYfwVrXt-w/s72-c/Screen+Shot+2019-01-08+at+7.03.35+pm.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-3196596006928336108</id><published>2018-07-01T16:15:00.002+10:00</published><updated>2018-08-29T16:09:12.009+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Eclipse"/><category scheme="http://www.blogger.com/atom/ns#" term="Google App Engine"/><category scheme="http://www.blogger.com/atom/ns#" term="Google Cloud Platform"/><category scheme="http://www.blogger.com/atom/ns#" term="Gralde"/><category scheme="http://www.blogger.com/atom/ns#" term="GWT"/><title type='text'>[GAE] How to create GWT project updated by Gradle for GAE on Eclipse</title><content type='html'>This is a stretch for the memo right now and it will be enhanced with photo or video later.&lt;br /&gt;
&lt;br /&gt;
1. Create a GWT project by GWT plugin&lt;br /&gt;
2. Right click on the project -&amp;gt; Configure -&amp;gt; Convert to App Engine Standard Project&lt;br /&gt;
3. Right click on the project -&amp;gt; Configure -&amp;gt; Add Gradle Nature&lt;br /&gt;
4. Create text file named build.gradle&amp;nbsp;file under project folder.&lt;br /&gt;
5. Write the configuration of this project in build.gradle.&lt;br /&gt;
&amp;nbsp; &amp;nbsp;For example:&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-sh&quot;&gt;&lt;/pre&gt;
&lt;pre class=&quot;prettyprint lang-sh&quot;&gt;//This section used for classpath setup&lt;/pre&gt;
&lt;pre class=&quot;prettyprint lang-sh&quot;&gt;def ROOT_PATH = &#39;{{ root_path_of_project }}&#39;
def LIBS_PATH = ROOT_PATH + &#39;{{ root_path_of_lib }}&#39;
def MODULE_PATH = ROOT_PATH + &#39;{{ root_path_of_module }}&#39;

//Uncomment this field when trying to fetch the latest version of libraries.
apply plugin: &#39;java&#39;
apply plugin: &#39;gwt&#39;
apply plugin: &#39;eclipse&#39;
apply plugin: &#39;war&#39;

//Script version
version = &#39;1.0&#39;

//this concept is used to define the external dependencies that are available to the classloader 
//during the execution of Gradle build script. In the declaration of dependencies only be used 
//the method classpath, and you can’t use the configurations compile , runtime, testCompile, etc. 
//because this block is just to declare external libraries references available to the classpath, 
//if you need to provide any configuration like compile or runtime you need to do outside of BuildScript block.
buildscript{
 repositories {
  //The repository where to fetch gwt gradle plugin
  jcenter()
  
//  maven {
//            url &#39;http://dl.bintray.com/steffenschaefer/maven&#39;
//        }
 }
 
 dependencies {
  //0.6
  classpath &#39;de.richsource.gradle.plugins:gwt-gradle-plugin:0.6&#39;
 }
}


//Central repository to load the GWT library
//indicates where Gradle looks for any required dependency, in this case in the Maven central repository. 
//For this example get gwt libraries and automatically fetch gwt dependencies; 
//while the script is executing some lines like these appears in the console.
repositories{
 mavenCentral()
}

eclipse{
 //To setup output classess folder for gwt project
 classpath{
  defaultOutputDir=file(&quot;war/WEB-INF/classes&quot;)
 }
/*
 project{
  //To setup linked resource folder
  linkedResource name:&#39;{{ name_of_linked_ref }}&#39;, type:&#39;2&#39;, location: LIBS_PATH + &#39;{{ path_of_linked_ref }}&#39;
 }
 
    classpath {
        file {
            withXml {
                def node = it.asNode()
                node.appendNode(&#39;classpathentry&#39;, [kind: &#39;src&#39;, path: &#39;{{ name_of_linked_ref }}&#39;, exported: true])
            }
        }
    }
*/ 
}

gwt{
 gwtVersion=&#39;2.8.1&#39;
 modules &#39;com.digsarustudio.qbox.QBox&#39;
 
 sourceSets{
  main{
   java {
    srcDir &#39;src&#39;
   }
  }
  
  test{
   java {
    srcDir &#39;test&#39;
   }
  }  
 }
 
 logLevel = &#39;INFO&#39;
 
 minHeapSize = &quot;512M&quot;
 maxHeapSize = &quot;1024M&quot;
 
 superDev{
  noPrecompile=true
 }
 
}

dependencies {
 //google cloud sql factory - This is very important for the project which uses Cloud SQL as the database.
/* 
 compile &#39;com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.0.10&#39;
*/ 
 compile &#39;com.google.cloud.sql:mysql-socket-factory:1.0.9&#39;
 
 //Google Gruava - For Cloud SQL MySQL Socket Factory
 compile &#39;com.google.guava:guava:26.0-jre&#39;&lt;/pre&gt;
&lt;pre class=&quot;prettyprint lang-sh&quot;&gt;
&lt;/pre&gt;
&lt;pre class=&quot;prettyprint lang-sh&quot;&gt;  //[Optional] For NoClassDefFoundError while including MySQL Socket Factory Connector
  compile group: &#39;org.ow2.asm&#39;, name: &#39;asm&#39;, version: &#39;5.2&#39;&lt;/pre&gt;
&lt;pre class=&quot;prettyprint lang-sh&quot;&gt;}&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;strike&gt;6. Right click -&amp;gt; Gradle -&amp;gt; Refresh Gradle Project&lt;/strike&gt;(This will break the GAE project structure)&lt;br /&gt;
7. Reorganise the structure of folders to meet the GWT requirements&lt;br /&gt;
8. Copy the customised or 3rd party libraries under &lt;project_folder&gt;/war/WEB-INF/lib&lt;/project_folder&gt;&lt;br /&gt;
9. Change the .level FROM WARNING to INFO in the logging.properties file if you want to see the INFO log in the logger.&lt;br /&gt;
10. Add&amp;nbsp;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #c9dfff; font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;load-on-startup&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #c9dfff; font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;load-on-startup&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;under a required servlet tag in the web.xml and&amp;nbsp;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #c9dfff; font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;warmup-requests-enabled&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #c9dfff; font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;warmup-requests-enabled&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;monaco&amp;quot;; font-size: 11px;&quot;&gt;&amp;gt; into appengine-web.xml&amp;nbsp;&lt;/span&gt;if you need this servlet has to been initialised when this app starts up.&lt;br /&gt;
&lt;style type=&quot;text/css&quot;&gt; p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #c9dfff} span.s1 {color: #8bbbff} span.s2 {color: #e0e0e0} &lt;/style&gt;


&lt;br /&gt;
That&#39;s it. The next section will show how to deploy this GWT project upto the Google App Engine.&lt;br /&gt;
&lt;br /&gt;
Coming soon:&lt;br /&gt;
&amp;nbsp;1. How to make GWT project to use Cloud SQL in Java 8&lt;br /&gt;
&amp;nbsp;2. How to skip the file amount limitation of a GWT project which is going to upload to Google App Engine.&lt;br /&gt;
&amp;nbsp;3. How to initialise configuration of Web App when the app starts up.&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
&amp;nbsp;For point 6:&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;After refresh the project, Gradle will reset the content of &lt;span style=&quot;color: red;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;background-color: white; font-family: &amp;quot;monaco&amp;quot;; font-size: 10px;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;{{ project_folder }}/.settings/org.eclipse.wst.common.component&quot;&lt;/span&gt;. This leads to that Eclipse cannot deploy the GAE project due to the appengine-web.xml cannot be found. The plugins will go through {{ project_folder }}/WEB-INF to look for it. However, WEB-INF is under {{ project_folder }}/war for GWT. To fix this issues, please place the following text of section in to this file:&lt;/span&gt;&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;project-modules id=&quot;moduleCoreId&quot; project-version=&quot;1.5.0&quot;&amp;gt;
  &amp;lt;wb-module deploy-name=&quot;{{ project_name }}&quot;&amp;gt;
   &amp;lt;wb-resource deploy-path=&quot;/&quot; source-path=&quot;/war&quot; tag=&quot;defaultRootSource&quot; /&amp;gt;
        &amp;lt;wb-resource deploy-path=&quot;/WEB-INF/classes&quot; source-path=&quot;/src&quot;/&amp;gt;
        &amp;lt;wb-resource deploy-path=&quot;/WEB-INF/classes&quot; source-path=&quot;/test&quot;/&amp;gt;
   
   &amp;lt;property name=&quot;context-root&quot; value=&quot;{{ project_name }}&quot;/&amp;gt;
   &amp;lt;property name=&quot;java-output-path&quot; value=&quot;/{{ project_name }}/war/WEB-INF/classes&quot; /&amp;gt;
  &amp;lt;/wb-module&amp;gt;
&amp;lt;/project-modules&amp;gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;span class=&quot;s1&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;style type=&quot;text/css&quot;&gt; p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Monaco; color: #f4f4f4; background-color: #000000; background-color: rgba(0, 0, 0, 0.85)} span.s1 {font-variant-ligatures: no-common-ligatures} &lt;/style&gt; &lt;style type=&quot;text/css&quot;&gt; p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #c9dfff} span.s1 {color: #8bbbff} span.s2 {color: #e0e0e0} &lt;/style&gt;


</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/3196596006928336108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2018/07/gae-how-to-create-gwt-project-updated.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3196596006928336108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3196596006928336108'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2018/07/gae-how-to-create-gwt-project-updated.html' title='[GAE] How to create GWT project updated by Gradle for GAE on Eclipse'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-7550266453960825630</id><published>2016-03-19T18:38:00.000+10:00</published><updated>2016-03-20T20:40:43.479+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Code Highlight"/><category scheme="http://www.blogger.com/atom/ns#" term="Tools"/><category scheme="http://www.blogger.com/atom/ns#" term="Web App"/><title type='text'>[Tools] Blog Code Highlight - a tool generating highlighted code with Pretty Print in Blogger</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
[Tool]&lt;br /&gt;
&lt;a href=&quot;https://blog-code-highlight.appspot.com/&quot; target=&quot;_blank&quot;&gt;Blog Code Highlight&lt;/a&gt;&lt;br /&gt;
Version: 1.0.1 Beta&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Introduction:&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; When highlighting code in Blogger as following:&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-cpp&quot;&gt;class MyClass
{
    private:
        int Counter;
        std::vector&amp;lt;int&amp;gt; mCountList;

    public:
        MyClass(void);
        
    public:
        void Show(void);
}&lt;/pre&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;The HTML code has to be generated manually in the post as follows:&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;pre class=&quot;prettyprint lang-html&quot;&gt;&amp;lt;pre class=&quot;prettyprint lang-cpp&quot;&amp;gt;
class MyClass
{
    private:
        int Counter;
        std::vector&lt;b&gt;&lt;i&gt;&amp;amp;lt&lt;/i&gt;&lt;/b&gt;;int&lt;b&gt;&lt;i&gt;&amp;amp;gt&lt;/i&gt;&lt;/b&gt;; mCountList;

    public:
        MyClass(void);
        
    public:
        void Show(void);
}
&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; It is easy to make a mistake with the wrong typing causes&amp;nbsp;exception&amp;nbsp;occurred and not convenient to modify if the code is in HTML or XML because of some symbols(&amp;lt;, &amp;gt;, &amp;nbsp;&amp;amp;) are the reserved characters in the markup languages. Those problems confused me while I tried to write the blog with code&amp;nbsp;if I didn&#39;t use the highlighting code frequently. In order to solve this problem and improve the efficiency of writing blog, I developed this tool as follows to help me convert the code of languages Google Code-Prettify supported into HTML code.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; &amp;nbsp;In this post, I would like to introduce how to use this tool to get correct (so far) HTML code for the Blogger.&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;How to use:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Goes to&amp;nbsp;&lt;a href=&quot;https://blog-code-highlight.appspot.com/&quot; target=&quot;_blank&quot;&gt;https://blog-code-highlight.appspot.com&lt;/a&gt;&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Type or paste the source code in the text area on the left-hand side.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Choose the language type which supported by Google Code-Prettify listed as follows: &lt;br /&gt;list here. &lt;br /&gt;
&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Choose the version of HTML if you want to generate the code in HTML5.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Tick &lt;b&gt;Show Line Number&lt;/b&gt; if you want to show line number in the code. In addition, the first line number can be specified.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Copy the formatted code from the &lt;b&gt;Outcome&lt;/b&gt; session and paste it into your blog.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNBiZVrMszkBMDRa6Edm_yUGjjBfQoEkG3TD5fJToPQLBcuMAR0vRLqeZdc9WV0YYxGhvZGtr-q0SnSaHVMRvwVVbCzhV02QkSb-YqrcF5EkwKApG90lcrhO5fdQDGKPWCD9VYB3zbwI4/s1600/v1.0.1+Beta.tiff&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;225&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNBiZVrMszkBMDRa6Edm_yUGjjBfQoEkG3TD5fJToPQLBcuMAR0vRLqeZdc9WV0YYxGhvZGtr-q0SnSaHVMRvwVVbCzhV02QkSb-YqrcF5EkwKApG90lcrhO5fdQDGKPWCD9VYB3zbwI4/s400/v1.0.1+Beta.tiff&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;&lt;a href=&quot;https://blog-code-highlight.appspot.com/&quot;&gt;[Click Here]&lt;/a&gt;&amp;nbsp;goes to this tool.&lt;/b&gt;&lt;/div&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt; &lt;b&gt;[Reference]&lt;/b&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/google/code-prettify&quot;&gt;Google / code-prettify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.w3schools.com/html/html_entities.asp&quot;&gt;HTML Entities&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
PS. Sorry for the ads. I need to get some funds if the quota is running out.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/7550266453960825630/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2016/03/tools-blog-code-highlight-tool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/7550266453960825630'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/7550266453960825630'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2016/03/tools-blog-code-highlight-tool.html' title='[Tools] Blog Code Highlight - a tool generating highlighted code with Pretty Print in Blogger'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNBiZVrMszkBMDRa6Edm_yUGjjBfQoEkG3TD5fJToPQLBcuMAR0vRLqeZdc9WV0YYxGhvZGtr-q0SnSaHVMRvwVVbCzhV02QkSb-YqrcF5EkwKApG90lcrhO5fdQDGKPWCD9VYB3zbwI4/s72-c/v1.0.1+Beta.tiff" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-3369925774432823634</id><published>2016-03-18T11:48:00.001+10:00</published><updated>2016-03-18T11:48:11.443+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Ant"/><title type='text'>[Ant]How to build a property file (Build.property)</title><content type='html'>&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;b&gt;How to name the property file:&lt;/b&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; &amp;nbsp;It is easy and simple to setup a property file for Ant build. Normally, the name of property file is&amp;nbsp;&lt;b&gt;build.properties&lt;/b&gt;, but it could be named as &lt;b&gt;build.properties.dev or build.properties.test&lt;/b&gt; based on the same deployment environments to be run in different settings. The benefits of using suffix &lt;b&gt;as .xxx &lt;/b&gt;are:&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;The build file can be reused for different execution environment with different property setting, such as developing, testing or release.&lt;/li&gt;
&lt;li&gt;Only the name of property file needs to be changed in the build.xml file while the target or source changed. It could reduce the typing error and time cost.&lt;/li&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;How to setup the properties:&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; Each property is illustrated by a name and a value connected by a equals sign (=) in a line.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; For example:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;
  src=c:\source file
  target.dir=d:\testing
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; In this case, dot symbol (.) could be a part of the name. It could be used to classify the properties into a group.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;How to comment in the property file:&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; Hash character (#) is used as the symbol to make a line as a comment.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; For example:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;
  ######################
  # This is Header
  #####################

  #Set soruce folder
  src.dir=c:\source file

  #Set destination folder
  target.dir=d:\testing&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;b&gt;[Reference]&lt;/b&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tutorialspoint.com/ant/ant_property_files.htm&quot;&gt;Ant - Property Files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.avajava.com/tutorials/lessons/how-do-i-use-a-build-properties-file.html&quot;&gt;How do I use a build.properties file&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/3369925774432823634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2016/03/anthow-to-build-property-file.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3369925774432823634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/3369925774432823634'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2016/03/anthow-to-build-property-file.html' title='[Ant]How to build a property file (Build.property)'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-509681442768785569</id><published>2016-01-31T13:23:00.003+10:00</published><updated>2017-05-25T06:09:45.314+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Apache"/><category scheme="http://www.blogger.com/atom/ns#" term="Mac OS X 10.11.3"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><title type='text'>[Apache] Configure Apache for PHP in Mac OS X 10.11.3 El Capitan</title><content type='html'>&lt;div&gt;
&lt;b&gt;[Versions]&lt;/b&gt;&lt;br /&gt;
&lt;table border=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;OS:&lt;/td&gt;
&lt;td&gt;Mac OS X 10.11.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;Apache:&lt;/td&gt;
&lt;td&gt;2.4.16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;PHP:&lt;/td&gt;
&lt;td&gt;5.5.30&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;In order to develop and test web pages on the local web server, I googled some blogs to figure out what I have to do. It took me a couple of hours to search and test which approach is workable. Finally, I found that&amp;nbsp;&lt;a href=&quot;https://donatstudios.com/PHP-in-OS-X-Yosemite&quot; target=&quot;_blank&quot;&gt;Configure Apache for PHP in OS X 10.10 Yosemite / 10.11 El Capitan&lt;/a&gt; written by Donat shows me how to set web pages up under home folder of the current user and &lt;a href=&quot;http://jason.pureconcepts.net/2014/11/configure-apache-virtualhost-mac-os-x/&quot; target=&quot;_blank&quot;&gt;Configuring Apache Virtual Hosts on Mac OS X&lt;/a&gt; posted by McCreary indicates how to set a domain name pointing to localhost. In this post, I am going to demonstrate how to setup both approach in my Mac.&lt;/div&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #0b5394; font-size: large;&quot;&gt;&lt;b&gt;Before Setup:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;What have to be done:&lt;/b&gt;&lt;br /&gt;
Check the version of Apache by the following command:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-bsh&quot;&gt;sudo apachectl -v&lt;/code&gt;
&lt;/pre&gt;
&lt;br /&gt;
Check the version of PHP by the following command:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-bsh&quot;&gt;sudo apachectl -v&lt;/code&gt;
&lt;/pre&gt;
&lt;span style=&quot;color: #0b5394; font-size: large;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt; &lt;span style=&quot;color: #0b5394; font-size: large;&quot;&gt;&lt;b&gt;Setup:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; &amp;nbsp; For the following demonstration, &lt;var&gt;{username}&lt;/var&gt; represents the current username used to login operating system and &lt;var&gt;{servername}&lt;/var&gt; represents the target hostname used to access the local website.&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Make sure there is a &lt;strong&gt;Sites&lt;/strong&gt; folder in the home directory. If not, create it and ensure the permission is 644(dr-xr--r--). If it is not, use the following command to change it:&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-bsh&quot;&gt;sudo chmod 644 Sites&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Make sure &lt;strong&gt;/etc/apache2/users/&lt;var&gt;{username}.conf&lt;/var&gt;&lt;/strong&gt; is existed. If not, create it. In addition, update this file as follows:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;&amp;lt;Directory &quot;/Users/{username}/Sites/&quot;&amp;gt;
    Options Indexes Multiviews FollowSymLinks
    Require all granted
    AllowOverride All
    Order allow,deny
    Allow from all
&amp;lt;/Directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Add virtual host into &lt;strong&gt;/etc/apache2/extra/httpd-vhosts.conf&lt;/strong&gt; as following:&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;&amp;lt;VirtualHost *:80&amp;gt;
  ServerName &lt;var&gt;{servername}&lt;/var&gt;
  DocumentRoot /Users/&lt;var&gt;{username}&lt;/var&gt;/Sites
&amp;lt;/VirtualHost&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #0b5394; font-size: large;&quot;&gt;&lt;b&gt;Configuration:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Uncomment the following lines in &lt;strong&gt;/etc/apache2/httpd.conf&lt;/strong&gt;: &lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;LoadModule deflate_module libexec/apache2/mod_deflate.so
LoadModule userdir_module libexec/apache2/mod_userdir.so
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
LoadModule php5_module libexec/apache2/libphp5.so
Include /private/etc/apache2/extra/httpd-userdir.conf
Include /private/etc/apache2/extra/httpd-vhosts.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Then add &lt;strong&gt;index.php&lt;/strong&gt; to the &lt;strong&gt;DirectoryIndex&lt;/strong&gt;&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;&amp;lt;IfModule dir_module&amp;gt;
    DirectoryIndex index.html &lt;strong&gt;index.php&lt;/strong&gt;
&amp;lt;/IfModule&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Uncomment the following line in &lt;strong&gt;/etc/apache2/extra/httpd-userdir.conf&lt;/strong&gt;&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;Include /private/etc/apache2/users/*.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;Restart Apache:&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;sudo apachectl restart&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;li&gt;If there is any problem happened, run the following command to see the error messages:&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;sudo apachectl configtest&lt;/code&gt;&lt;/pre&gt;
&lt;/ol&gt;
&lt;br /&gt;
&lt;span style=&quot;color: #0b5394; font-size: large;&quot;&gt;&lt;b&gt;Test:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;So far, the web server has been established and the pages can be accessed by the following URL:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;http://localhost/~&lt;var&gt;{username}&lt;/var&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;If there is no web page in this folder, it will show the index of web pages. Put the HTML file or the PHP file to test it.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;color: #0b5394; font-size: large;&quot;&gt;Mapping to the specific domain name:&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;With regard to the URL shown above, it is not convenient for me to access every website with the long typing because I might have plenty of website on my local machine. In order to reduce the expenses of typing, I would rather use a shortened link to do it. The following steps show&amp;nbsp;how to setup a specific domain name for the website.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Open /etc/hosts as follows command:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;sudo vim /etc/hosts&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Append the server name and target IP at the end of this file. In this case, 127.0.0.1 can be set for multiple server names. &lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost

&lt;strong&gt;127.0.0.1       &lt;var&gt;{servername}&lt;/var&gt;&lt;/strong&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Clear the local DNS cache by the following command: &lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;dscacheutil -flushcache&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Restart Apache.&lt;/li&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;sudo apachectl restart&lt;/code&gt;&lt;/pre&gt;
&lt;/ol&gt;
&lt;b style=&quot;color: #0b5394; font-size: x-large;&quot;&gt;Test:&lt;/b&gt;&lt;br /&gt;
Just type:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code language=&quot;bsh&quot;&gt;http://&lt;var&gt;{servername}&lt;/var&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;[Reference]&lt;/b&gt;&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://donatstudios.com/PHP-in-OS-X-Yosemite&quot; target=&quot;_blank&quot;&gt;Configure Apache for PHP in OS X 10.10 Yosemite / 10.11 Capitan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://jason.pureconcepts.net/2014/11/configure-apache-virtualhost-mac-os-x/&quot; target=&quot;_blank&quot;&gt;Configuring Apache Virtual Hosts on Mac OS X&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://discussions.apple.com/docs/DOC-3083&quot; target=&quot;_blank&quot;&gt;Setting up a local web server on OS X&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/509681442768785569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2016/01/apache-configure-apache-for-php-in-mac.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/509681442768785569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/509681442768785569'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2016/01/apache-configure-apache-for-php-in-mac.html' title='[Apache] Configure Apache for PHP in Mac OS X 10.11.3 El Capitan'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-9187927317179052003</id><published>2014-12-12T12:24:00.002+10:00</published><updated>2014-12-12T12:24:52.024+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Eclipse"/><category scheme="http://www.blogger.com/atom/ns#" term="GWT"/><title type='text'>[GWT]How to use Google Web Toolkits - Installation</title><content type='html'>&lt;table border=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;GWT version:&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;4.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;Eclipse version:&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;4.4 (Luna)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;Java version:&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;1.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;right&quot;&gt;OS:&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;Mac OS X 10.10.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; First of all, &quot;&lt;a href=&quot;http://www.gwtproject.org/&quot; target=&quot;_blank&quot;&gt;Google Web Toolkit (GWT)&lt;/a&gt; is a development toolkit for building and optimizing complex browser-based application.&quot; The purpose of this toolkit is to make possible productive development of high-performance web applications without the developer having to be an expert in browser quirks, XMLHttpRequest, and JavaScript. It&#39;s open source and completely free as well. In this toolkit, it contains &lt;a href=&quot;http://www.gwtproject.org/learnmore-sdk.html&quot; target=&quot;_blank&quot;&gt;SDK&lt;/a&gt; and &lt;a href=&quot;https://developers.google.com/eclipse/index&quot; target=&quot;_blank&quot;&gt;Plugin for Eclipse&lt;/a&gt;&amp;nbsp;so that we can use &lt;a href=&quot;https://eclipse.org/home/index.php&quot; target=&quot;_blank&quot;&gt;Eclipse&lt;/a&gt; as the editor to develop web application we want. The steps of installation will be illustrated as follows.&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: justify;&quot;&gt;
&amp;nbsp; 1.Setup Eclipse:&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;Downloading Eclipse from &lt;a href=&quot;https://www.eclipse.org/downloads/&quot; target=&quot;_blank&quot;&gt;official website&lt;/a&gt;. Normally, I will choose &lt;a href=&quot;https://eclipse.org/downloads/packages/eclipse-ide-java-ee-developers/lunar&quot; target=&quot;_blank&quot;&gt;Eclipse IDE for Java EE Developers &lt;/a&gt;as my IDE because I prefer to use this tool to develop C or C++ on Mac. Extracting zip file directly when the downloading finished.&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; 2.Get Plugin for Eclipse (including SDKs)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; There are two ways to get Plugin for Eclipse, one is downloading from &lt;a href=&quot;http://www.gwtproject.org/download.html&quot; target=&quot;_blank&quot;&gt;download page of GWT&lt;/a&gt;, another one is installing Google Plugin for Eclipse via a link such as &lt;span style=&quot;color: #007000; font-family: Courier, &#39;Courier New&#39;, monospace; font-size: 12px;&quot;&gt;http://dl.google.com/eclipse/plugin/x.x&lt;/span&gt;. The &quot;x.x&quot; is the version of Eclipse, such as 4.3 for Kepler and 4.4 for Luna. According to the &lt;a href=&quot;http://www.gwtproject.org/usingeclipse.html&quot; target=&quot;_blank&quot;&gt;user guide of configuration Eclipse&lt;/a&gt;, we need to use Install dialog to install this plugin. The steps of installation are as following:&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; I. To choose &quot;&lt;u&gt;&lt;i&gt;Install New Software&lt;/i&gt;&lt;/u&gt;&quot;.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDhrfaE18JjWXsl_h4KqR1AxkI20yetQgNl0sY_m_Curk2uk_DDaJydBR9n-qJf-wDN3u6rLPu0nT0qmXzehoiIvywHcNOI6J4Qq9O1TKcFi-8wD7DVNeobx6X_zIFixRol50PWtBkD78/s1600/Screen+Shot+2014-12-12+at+11.58.55+am.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDhrfaE18JjWXsl_h4KqR1AxkI20yetQgNl0sY_m_Curk2uk_DDaJydBR9n-qJf-wDN3u6rLPu0nT0qmXzehoiIvywHcNOI6J4Qq9O1TKcFi-8wD7DVNeobx6X_zIFixRol50PWtBkD78/s1600/Screen+Shot+2014-12-12+at+11.58.55+am.png&quot; height=&quot;251&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp; &amp;nbsp; II. Checking &quot;&lt;u&gt;&lt;i&gt;Google Plugin for Eclipse(required)&lt;/i&gt;&lt;/u&gt;&quot; and clicking &quot;&lt;u&gt;&lt;i&gt;Next&lt;/i&gt;&lt;/u&gt;&quot; button to complete the installation.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgISZkqEvLB8FuF8QMgCtvC0JiemMceUoRDv6bDCRMS3fykK1sb5Fg3iXGDSACQynD_iLw96NOyH42y0t05ybrh5X-n3WenURc5LR3rzMQqs8SqeIGypv1zEHtx1pa2TeXD3gQTcXN-bL0/s1600/1.Install+Google+Plugin+for+Eclipse.tiff&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgISZkqEvLB8FuF8QMgCtvC0JiemMceUoRDv6bDCRMS3fykK1sb5Fg3iXGDSACQynD_iLw96NOyH42y0t05ybrh5X-n3WenURc5LR3rzMQqs8SqeIGypv1zEHtx1pa2TeXD3gQTcXN-bL0/s1600/1.Install+Google+Plugin+for+Eclipse.tiff&quot; height=&quot;480&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp; &amp;nbsp; The Eclipse needs to be restarted after installation. When the Eclipse restarted, we can use it for developing web application with GWT.&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/9187927317179052003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2014/12/gwthow-to-use-google-web-toolkits.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/9187927317179052003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/9187927317179052003'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2014/12/gwthow-to-use-google-web-toolkits.html' title='[GWT]How to use Google Web Toolkits - Installation'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDhrfaE18JjWXsl_h4KqR1AxkI20yetQgNl0sY_m_Curk2uk_DDaJydBR9n-qJf-wDN3u6rLPu0nT0qmXzehoiIvywHcNOI6J4Qq9O1TKcFi-8wD7DVNeobx6X_zIFixRol50PWtBkD78/s72-c/Screen+Shot+2014-12-12+at+11.58.55+am.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-2581306627120973831</id><published>2014-03-26T16:52:00.002+10:00</published><updated>2014-03-26T16:52:47.642+10:00</updated><title type='text'>This is what we facing Nowadays.</title><content type='html'>I&#39;m not sure what I can do to support the participants fighting for their future.&lt;br /&gt;
The only I can do is distributing what happened in my home country.&lt;br /&gt;
Let other people know what our teenagers caring and facing.&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;//www.youtube.com/embed/eIo9fCAUPAM&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/2581306627120973831/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2014/03/this-is-what-we-facing-nowadays.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/2581306627120973831'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/2581306627120973831'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2014/03/this-is-what-we-facing-nowadays.html' title='This is what we facing Nowadays.'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-4269543944703149191</id><published>2013-06-07T18:48:00.001+10:00</published><updated>2013-06-27T17:46:47.333+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Eclipse"/><category scheme="http://www.blogger.com/atom/ns#" term="SDK Tools"/><title type='text'>[Eclipse]新建立的Android專案出現&quot;R cannot be resolved to a variable&quot;</title><content type='html'>&lt;div&gt;
這問題其實是很詭異的，因為同樣是今年，只是在SDK是使用r20以前的時候，都可以正常建立新專案(這時的Target SDK為2.3.3)。但今天把它更新到r22.0後，就出現了標題所列的問題。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
找了很多網路資料，不管是Clean後又Build，還是專案重建，都一樣的結果。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;strike&gt;後來找到這篇「&lt;a href=&quot;http://blog.kenyang.net/2012/11/android-r-cannot-be-resolved-to-variable.html&quot; target=&quot;_blank&quot;&gt;Android: r cannot be resolved to a variable&lt;/a&gt;」 ，他有提到是因為SDK4.x的專案建立的時候，會在res底下多出了value-v11以及value-v14這兩個資料夾。然後這個時候設定的Minimun Required SDK是設定為2.3.3。所以根據那篇的說法，這樣2.3.3的SDK是不認識那兩個資料夾，所以就變得無法產生R.java。&lt;/strike&gt;&lt;/div&gt;
&lt;div&gt;
&lt;strike&gt;&lt;br /&gt;&lt;/strike&gt;&lt;/div&gt;
&lt;div&gt;
&lt;strike&gt;後來專案刪掉後重建的時候，把Minimun Required SDK選擇成4.2，就正常可以產生R.java了。&lt;/strike&gt;&lt;/div&gt;
&lt;div&gt;
&lt;strike&gt;&lt;br /&gt;&lt;/strike&gt;&lt;/div&gt;
&lt;div&gt;
&lt;strike&gt;後來又為了要確認問題，所以把Minimun Required SDK、Target SDK、以及Compile With都設定為2.3.3。嘿嘿，好玩了，建立出來的專案一樣不能產生R.java。&lt;/strike&gt;&lt;/div&gt;
&lt;div&gt;
&lt;strike&gt;&lt;br /&gt;&lt;/strike&gt;&lt;/div&gt;
&lt;div&gt;
&lt;strike&gt;所以這意思是，SDK Tools用了r22以後的，就不能編譯給2.3.3用的APP嚕？&lt;/strike&gt;&lt;br /&gt;
&lt;br /&gt;
後記：&lt;br /&gt;
結果打完這篇之後，建出來的專案又不正常了。&lt;br /&gt;
之後又找了其他參考，有人指出是需要Android SDK Build-tools。所以在更新這個tools之後，r就一切都正常了。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
然後如果Unity還在用3.5.7以下的話，Android SDK Platform-tools請不要更新，不然會發生Unity無法編譯apk的慘劇。唯一的解決辦法就是把，Android SDK Platform-tools降版本至16.0.2以下，以及不要安裝Android SDK Build-tools。&lt;br /&gt;
&lt;br /&gt;
(2013/06/27 - 目前確認，造成Unity無法編譯的是&lt;b&gt;Android SDK Build-tools&lt;/b&gt;，僅需把&lt;b&gt;Android SDK Build-tools&lt;/b&gt;移除掉，Unity就可以正常編譯了。)&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/4269543944703149191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2013/06/eclipseandroidr-cannot-be-resolved-to.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4269543944703149191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/4269543944703149191'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2013/06/eclipseandroidr-cannot-be-resolved-to.html' title='[Eclipse]新建立的Android專案出現&quot;R cannot be resolved to a variable&quot;'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-5364046866804148192</id><published>2013-05-30T16:46:00.000+10:00</published><updated>2013-05-30T16:51:03.173+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="JAR"/><category scheme="http://www.blogger.com/atom/ns#" term="Unity Plugins"/><category scheme="http://www.blogger.com/atom/ns#" term="Unity(3.5.7f6)"/><title type='text'>[Unity]使用Plugin - JAR將二進位檔寫入至SDCard</title><content type='html'>Version:&lt;br /&gt;
&amp;nbsp; 1.Unity &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; : 3.5.7f6&lt;br /&gt;
&amp;nbsp; 2.Anddroid &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;: 2.3.3&lt;br /&gt;
&amp;nbsp; 3.Android SDK Tools : r22&lt;br /&gt;
&amp;nbsp; 4.Eclipse &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;: Juno SR2&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; 目前想在Unity上，將資料寫入到檔案內，可以使用&lt;a href=&quot;http://msdn.microsoft.com/zh-tw/library/system.io.file(v=vs.80).aspx&quot; target=&quot;_blank&quot;&gt;System.io.File&lt;/a&gt;(C#)來進行純文字或是二進位資料的儲存。但是在Android上，如有需將檔案存入SDCard內，則需先設定檔案存取權限。在Android的app開發上，需要去新增&lt;a href=&quot;http://developer.android.com/reference/android/Manifest.permission.html#WRITE_EXTERNAL_STORAGE&quot; target=&quot;_blank&quot;&gt;android.permission.WRITE_EXTERNAL_STORAGE&lt;/a&gt;。這個權限設定之後，就可以進行檔案的讀寫(在4.1以後，則需另外設定讀取權限，&lt;a href=&quot;http://developer.android.com/reference/android/Manifest.permission.html#READ_EXTERNAL_STORAGE&quot; target=&quot;_blank&quot;&gt;android.permission.READ_EXTERNAL_STORAGE&lt;/a&gt;)。然而這個權限設定，Unity幫我們做到了，因此我們不需要在另外設定AndroidManifest.xml，僅需將「PlayerSettings」-&amp;gt;「Per-Platform Settings」-&amp;gt;「Write Access」 設定為「SDCard」即可。&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTVXu18DB9HoczjhWN_KqCsMmeJ4owqw1woAtcdssPFMfm53qak0cBKURJMLYSLXCrCq_rvYYGQHmgRCujhUgd1tsF6hawIdS3yjxTPw3q0dxwLfxBEzGvNDGEVKyTkPOQkp7cJpTYjU0/s1600/01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTVXu18DB9HoczjhWN_KqCsMmeJ4owqw1woAtcdssPFMfm53qak0cBKURJMLYSLXCrCq_rvYYGQHmgRCujhUgd1tsF6hawIdS3yjxTPw3q0dxwLfxBEzGvNDGEVKyTkPOQkp7cJpTYjU0/s320/01.png&quot; width=&quot;222&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO27TjppwPZV0Oigd4-f2qPvmMpjOCRgS6HMhhmWR28s4qs0E4XB0NfeNZUHgz98MliCMeXKoc_rbY1Sq8LpNnNf5v2dEf_yvGnld73m7DApZchST0R6cZdMTphUYV0X9wNki082Qewvc/s1600/02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO27TjppwPZV0Oigd4-f2qPvmMpjOCRgS6HMhhmWR28s4qs0E4XB0NfeNZUHgz98MliCMeXKoc_rbY1Sq8LpNnNf5v2dEf_yvGnld73m7DApZchST0R6cZdMTphUYV0X9wNki082Qewvc/s320/02.png&quot; width=&quot;123&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; C#的讀寫檔方式，必須自行指定資料夾的路徑，所以如果當我們要把檔案寫道SDCard內的話，資料夾路徑會是「/mnt/sdcard/...」。如果SDCard的路徑被變更的話，那麼在程式內所指定的路徑就又要重新設定過。&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; 然而Android有提供取得SDCard的路徑功能，所以這邊就利用JAR的方式，讓Unity可以直接使用Android所提供的API，取得系統內所記錄的SDCard的實際路徑，並將檔案寫入到SDCard內。&lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
在JAR內的程式碼為：&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-java linenums&quot;&gt;package com.drillingsaru.io.sdcard;  
 //Java  
 import java.io.File;  
 import java.io.FileOutputStream;  
 import java.io.IOException;  
 //android  
 import android.os.Environment;  
 import android.util.Log;  
 public class BinaryFileIO   
 {  
 //Write binary data into a file  
     public void WriteData(String FileName, byte[] DataBuf)  
     {  
         if( !this.IsExternalStorageMounted() ) {  
             this.mErrNo = ERR_STORAGE_NOT_MOUNTED;  
             return;  
         }  
         try  
         {  
         //Get the path of root folder (Return = /mnt/sdcard )  
             File rootDir = Environment.getExternalStorageDirectory();  
         //Create a output stream object  
             FileOutputStream outStream = new FileOutputStream(new File(rootDir.getPath(), FileName));  
         //Write Data                          
             outStream.write(DataBuf);  
         //Flush it  
             outStream.flush();  
         //Close self  
             outStream.close();  
             this.mErrNo = ERR_NONE;  
         }catch(Exception e){  
             Log.d(&quot;--WriteData--&quot;, e.getMessage());  
         }          
     }  
 }  
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
在Unity的程式碼為
&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-cs linenums&quot;&gt;using UnityEngine;  
 using System.Collections;  
 using System.Collections.Generic;  
 public class WriteData2SDCard : MonoBehaviour   
 {  
 #region Definition      
 /// &amp;lt;summary&amp;gt;  
 /// The package name and class name &amp;nbsp;
 /// package name = com.DrillingSaru.io.sdcard
 /// &amp;lt;/summary&amp;gt;  
     public readonly string PACKAGE_CLASS_NAME = &quot;com.drillingsaru.io.sdcard.BinaryFileIO&quot;;  
 /// &amp;lt;summary&amp;gt;  
 /// Student information  
 /// &amp;lt;/summary&amp;gt;  
     public    class StudentInfo  
     {  
         public    int    Language        = 0;  
         public    int    Math    = 0;  
         public    int    Science    = 0;  
         public StudentInfo(int lang, int math, int science)  
         {  
             this.Language    = lang;  
             this.Math        = math;  
             this.Science    = science;  
         }  

         public StudentInfo(byte[] DataBuf)  
         {  
             this.Set(DataBuf);  
         }

     //轉換成byte陣列
         public byte[] GetBytes()  
         {  
             List&amp;lt;byte&amp;gt; RtnData = new List&amp;lt;byte&amp;gt;();  
             RtnData.AddRange(System.BitConverter.GetBytes(this.Language));  
             RtnData.AddRange(System.BitConverter.GetBytes(this.Math));  
             RtnData.AddRange(System.BitConverter.GetBytes(this.Science));  
             return RtnData.ToArray();  
         } 

     //轉換成結構資料
          public void Set(byte[] DataBuf)
          {
             int Offset = sizeof(int);
             int Shift = 0;
  
             this.Language = System.BitConverter.ToInt32(DataBuf, Shift);
             Shift += Offset;
   
             this.Math = System.BitConverter.ToInt32(DataBuf, Shift);
             Shift += Offset;
   
             this.Science = System.BitConverter.ToInt32(DataBuf, Shift);
             Shift += Offset;      
         }
     }  
 #endregion      
 #region InputData  
 #endregion  
 #region DataMebmer  
     private    StudentInfo            mStudentInfo    = new StudentInfo(500, 5, 10);  
     private    AndroidJavaObject    mDataWriter        = null;  
 #endregion          
 #region MemberFunc  
     private void Init()  
     {          
         this.mDataWriter = new AndroidJavaObject(PACKAGE_CLASS_NAME);  
     }  

 /// &amp;lt;summary&amp;gt;  
 /// write binary data to file
 /// &amp;lt;/summary&amp;gt;
     private void WriteData()  
     {  
         if( this.mDataWriter == null )  
             return;  
     //設定傳入參數
         object[] args = new object[2];  
         args[0] = &quot;testfile.bin&quot;;  
         args[1] = (object)this.mStudentInfo.GetBytes();  

     //呼叫函式
         this.mDataWriter.Call(&quot;WriteData&quot;, args);  
     }  

/// &amp;lt;summary&amp;gt;  
/// read binary data from file
/// &amp;lt;/summary&amp;gt;
     private void ReadData_Test()
     {
         if( this.mDataWriter == null )
             return;
  
         byte[] RtnList = new byte[1024];
         object[] args = new object[1];
         args[0] = &quot;testfile.bin&quot;;
         RtnList = this.mDataWriter.Call&lt;byte&gt;(&quot;ReadData&quot;, args);  
  
         this.mStudentInfo.Set(RtnList);
     }
#endregion          

 #region SystemFunc  
     void Awake()  
     {  
         this.Init();  
     }  
     // Use this for initialization  
     void OnEnable ()   
     {  
         this.WriteData();  
     }  
     void Update ()   
     {  
     }  
 #endregion      
 }  &lt;/byte&gt;&lt;/pre&gt;
&lt;br /&gt;
用了上述的Plugin後，就可以將二進位檔存至SDCard了。</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/5364046866804148192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2013/05/unityplugin-jarsdcard.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/5364046866804148192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/5364046866804148192'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2013/05/unityplugin-jarsdcard.html' title='[Unity]使用Plugin - JAR將二進位檔寫入至SDCard'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTVXu18DB9HoczjhWN_KqCsMmeJ4owqw1woAtcdssPFMfm53qak0cBKURJMLYSLXCrCq_rvYYGQHmgRCujhUgd1tsF6hawIdS3yjxTPw3q0dxwLfxBEzGvNDGEVKyTkPOQkp7cJpTYjU0/s72-c/01.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-7031210782973640110</id><published>2013-05-28T18:06:00.000+10:00</published><updated>2013-11-13T11:56:37.824+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="JAR"/><category scheme="http://www.blogger.com/atom/ns#" term="Unity Plugins"/><category scheme="http://www.blogger.com/atom/ns#" term="Unity(3.5.7f6)"/><title type='text'>[Unity]Plugin建立過程 - JAR</title><content type='html'>Version:&lt;br /&gt;
&amp;nbsp; 1.Unity &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;: 3.5.7f6&lt;br /&gt;
&amp;nbsp; 2.Anddroid &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; : 2.3.3&lt;br /&gt;
&amp;nbsp; 3.Android SDK Tools : r22&lt;br /&gt;
&amp;nbsp; 4.Eclipse &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; : Juno SR2&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;這邊使用簡單的計算範例來呈現，如何建立要給Unity使用的Plugin。 這邊的Plugin是使用JAR。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;1.建立新的Android專案&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp; &amp;nbsp; I.在Eclipse介面上，點選「File」-&amp;gt;「New」-&amp;gt;「Project」。&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9BaCgh3xWvKy8Ka9T8hJphpvnfGFBjFVNfzJsCmcvnh1HlQ-PWP6db4H9Q1omXcCYlaCqlTagH2QjJkL-WSR1f1n7j9auyaX8Rjsx2onjPTP-YzRFIPD6G1YrJ_MPYu8Z9HbaUTp8_L4/s1600/01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9BaCgh3xWvKy8Ka9T8hJphpvnfGFBjFVNfzJsCmcvnh1HlQ-PWP6db4H9Q1omXcCYlaCqlTagH2QjJkL-WSR1f1n7j9auyaX8Rjsx2onjPTP-YzRFIPD6G1YrJ_MPYu8Z9HbaUTp8_L4/s320/01.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp; &amp;nbsp; II.選擇「Android Application Project」。&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjmeYSTH4loENJBcXZaZRNfLuIlJt_0STkDvVtEPlKYU_eZzBcDdxICqSnd-nn-p-1meo75wBmjjmS_K68c91puEQQzBn0yqvPgGEbWt1lCe6m9MqHjc1VkIc2O6HgGE6imqmU9HyazIk/s1600/02.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjmeYSTH4loENJBcXZaZRNfLuIlJt_0STkDvVtEPlKYU_eZzBcDdxICqSnd-nn-p-1meo75wBmjjmS_K68c91puEQQzBn0yqvPgGEbWt1lCe6m9MqHjc1VkIc2O6HgGE6imqmU9HyazIk/s320/02.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp; &amp;nbsp; III.設定相關設定，這邊就依個人的需求，自行設定即可。&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqNjsDyZIQlplyKZLvwxbqlF0LVKEX4XPX-wikdN9PGQUB_DFVv2JhFFNHXqIme7X_iuV1Ci7lBsr2MuP4Zo_3yFNj6cc97ZtW-aiphsn1PRD0hm-89yZGxDcvgIUQhPWPJHPi9vVRY1Q/s1600/03.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqNjsDyZIQlplyKZLvwxbqlF0LVKEX4XPX-wikdN9PGQUB_DFVv2JhFFNHXqIme7X_iuV1Ci7lBsr2MuP4Zo_3yFNj6cc97ZtW-aiphsn1PRD0hm-89yZGxDcvgIUQhPWPJHPi9vVRY1Q/s320/03.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&amp;nbsp; &amp;nbsp; IV.專案建立過程中，[Create custom launcher icon]與[Create activity]預設都會被勾選。但是目前並用不到這兩個設定，所以在這裡就把這兩個設定設定為不選擇。&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0cfOcPwJS1042CfI4diY1Qv02ZvwyNrF6xs1BPDpQf-EF0ZhjjRmMkeluVTLa2QBa6p9R6gaoWxobsjVYRYT5bdzKA_w0kYmC8IdFApzPzidt8wmApoxo7tLHMfKzYsGCTTaIBOCoRv8/s1600/04.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0cfOcPwJS1042CfI4diY1Qv02ZvwyNrF6xs1BPDpQf-EF0ZhjjRmMkeluVTLa2QBa6p9R6gaoWxobsjVYRYT5bdzKA_w0kYmC8IdFApzPzidt8wmApoxo7tLHMfKzYsGCTTaIBOCoRv8/s320/04.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; V.取消[Create custom launcher icon]與[Create activity]後，按下「Finish」按鈕，就可以完成專案建立的流程了。&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAHlJ1wg3hu2p2tLIFKCsRNECwaxdvOYvxv1jVW2w8Qjhq-d0Migejdzjw4SGFT1mETXiL-Gek2t6H4eEyVYsT7Yree47eg2Nnj19wbSUx33D31W6mZMHy4qutVbkC_y4bWbyn-Pvwwmg/s1600/05.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAHlJ1wg3hu2p2tLIFKCsRNECwaxdvOYvxv1jVW2w8Qjhq-d0Migejdzjw4SGFT1mETXiL-Gek2t6H4eEyVYsT7Yree47eg2Nnj19wbSUx33D31W6mZMHy4qutVbkC_y4bWbyn-Pvwwmg/s320/05.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; VI.建立好的專案架構如下圖&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdArOGK6NmpVJZNdnq1q7fkNMvsxJIsYAeaVA-ky5XEbcYrLvmqmhKMTQEWfRnu4DfkM5HHgfv4rMFwi7gzLCi9rK4q_yjB7QNIMWvIPz4qxMZwW0yxCz4IBOzZ56gUQdINms83J6-rbE/s1600/06.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdArOGK6NmpVJZNdnq1q7fkNMvsxJIsYAeaVA-ky5XEbcYrLvmqmhKMTQEWfRnu4DfkM5HHgfv4rMFwi7gzLCi9rK4q_yjB7QNIMWvIPz4qxMZwW0yxCz4IBOzZ56gUQdINms83J6-rbE/s320/06.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; VII.加入新的[Package]：於[src]上按下滑鼠右鍵-&amp;gt;[New]-&amp;gt;[Package]&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKVTsWXArA2EOpvBuUk5ECpdQWfZGW0xlU7jHyabfyelcJWqPHJNgtLUNfAcdHnyAH0SVo49x-ODXso1O3PDo3SCu52-zMVVP4IDqx4jQAb8hR3oS8vqHq6TE6nSb6w5_05UCF9uMleiI/s1600/07.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKVTsWXArA2EOpvBuUk5ECpdQWfZGW0xlU7jHyabfyelcJWqPHJNgtLUNfAcdHnyAH0SVo49x-ODXso1O3PDo3SCu52-zMVVP4IDqx4jQAb8hR3oS8vqHq6TE6nSb6w5_05UCF9uMleiI/s320/07.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; VIII.設定[Package]的名稱，[Package]的名稱會在Unity內使用到。&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOy3qTDxRdnOLwa_UxUuhh8KhFhOhYqQ_G7C9fsOQwtS7-ntmEkjcQ0hpB0xes-YkJvUgc7ipKHQhDALgFTdN57eocBXHcokOQNH7ybJv4TZIxjshjoU2J-uUfRT7ZlzlzDomxfqM59Q/s1600/08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnOy3qTDxRdnOLwa_UxUuhh8KhFhOhYqQ_G7C9fsOQwtS7-ntmEkjcQ0hpB0xes-YkJvUgc7ipKHQhDALgFTdN57eocBXHcokOQNH7ybJv4TZIxjshjoU2J-uUfRT7ZlzlzDomxfqM59Q/s320/08.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; IX.新增[Class]給[Package]在新建立好的[package]上按下滑鼠右鍵-&amp;gt;[New]-&amp;gt;[Class]&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcbIknzztfMmgt2DAz1DXAP_MFwD8OAPrIJqPda0ntwY85RMLvcnBFFh_YG3lOIDvonddqPkOjn1xFHNDhrqZCnI9mRtOQPa_MYc8nkQZkV-CxxAQBpfGQir2H2ytm_2MLAUgj2uicfco/s1600/09.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcbIknzztfMmgt2DAz1DXAP_MFwD8OAPrIJqPda0ntwY85RMLvcnBFFh_YG3lOIDvonddqPkOjn1xFHNDhrqZCnI9mRtOQPa_MYc8nkQZkV-CxxAQBpfGQir2H2ytm_2MLAUgj2uicfco/s320/09.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; X.設定[Class]的名稱，這邊設定的名稱之後也會在Unity內使用到。&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuPzgO3gNugJvDr1zFEFM31qC5rSRb2Z4RsvHNko3MorF7_41e-wvHuhQg-0Wi2AA2F0hIKTcZVg1PY1MTrt5fN4eHWv_oQkYnLLK83Go8EnO7ISrfFetlFLhC4Wmj65t4XsVH0m7fNC0/s1600/10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuPzgO3gNugJvDr1zFEFM31qC5rSRb2Z4RsvHNko3MorF7_41e-wvHuhQg-0Wi2AA2F0hIKTcZVg1PY1MTrt5fN4eHWv_oQkYnLLK83Go8EnO7ISrfFetlFLhC4Wmj65t4XsVH0m7fNC0/s320/10.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; XI.建立想要使用的功能的程式碼&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;A.Number Adder:&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-java linenums&quot;&gt;package com.calculator.numberincreasing;  
 public class NumberAdder   
 {  
     public int Add(int base, int factor)  
     {  
         return (base + factor);  
     }  
 }  
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;B.Number Multiple:&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-java linenums&quot;&gt;package com.calculator.numberincreasing;  
 public class NumberMultipler   
 {  
     public int Multiple(int base, int rate)  
     {  
         return (base * rate);  
     }  
 }  
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; XII.程式碼編寫完成後，就可以透過[Export]的方式將程式封裝，並交給Unity使用。&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;專案上按滑鼠右鍵-&amp;gt;[Export]。&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwBYFMW8tvoXCmVLqIREhJFCM8kqKuxEq7_7ju0XE35dinDiDV08TtgcmYY34TJwkbdYz2tipS_sQUniqtxR4728GenwBWJ8Mg6WOHSxp_LJ1AGEYthxedOx4oWG8Ze1DocgxXjTkib9E/s1600/11.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;268&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwBYFMW8tvoXCmVLqIREhJFCM8kqKuxEq7_7ju0XE35dinDiDV08TtgcmYY34TJwkbdYz2tipS_sQUniqtxR4728GenwBWJ8Mg6WOHSxp_LJ1AGEYthxedOx4oWG8Ze1DocgxXjTkib9E/s320/11.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; XIII.選擇[Java]-&amp;gt;[JAR File]&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRkKRTCSobIjNiNLwBXlXf843Pxgiv2uMAaRfbUnZ7o363TlThKr9CDpEWaagQc0yVCQMceKM2MXVIcsDbx10QWsAxFx9vhx69CTFaWfjggfAJqh5xjXM3SNyHd9gt5OWnWtdMKUBXl8M/s1600/12.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;251&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRkKRTCSobIjNiNLwBXlXf843Pxgiv2uMAaRfbUnZ7o363TlThKr9CDpEWaagQc0yVCQMceKM2MXVIcsDbx10QWsAxFx9vhx69CTFaWfjggfAJqh5xjXM3SNyHd9gt5OWnWtdMKUBXl8M/s320/12.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; XIV.把要匯出的資料勾選起來，這邊預設會勾選所有的資料夾。 然後指定JAR檔要輸出的位置即可。&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlOXj1JXitOkpWe9_O-gwMhzoiGENENeswWuVVChdwqJgPeAMlZT-BAkIHUmM25TwPEUnbBPlKSrkOwWShTgSKJbA9VY1Fe8B9hAXGTQHCtPAAtv-MbCR6lF1wUotlAWRNrUnisCeJ0JU/s1600/13.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;317&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlOXj1JXitOkpWe9_O-gwMhzoiGENENeswWuVVChdwqJgPeAMlZT-BAkIHUmM25TwPEUnbBPlKSrkOwWShTgSKJbA9VY1Fe8B9hAXGTQHCtPAAtv-MbCR6lF1wUotlAWRNrUnisCeJ0JU/s320/13.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;2.如何在Unity內使用JAR檔內的方法：&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
I.把JAR檔放到&quot;./Asset/Plugins/Android/&quot;下即可。(Plugins與Android資料夾皆需要自行建立)&lt;br /&gt;
&lt;br /&gt;
II.建立操作用的Script&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-cs linenums&quot;&gt;public class Calculator : MonoBehaviour   
 {  
     private int Org = 10;  
     private int factor = 20;  
     private int Mutiple = 30;  
     private int Added = 0;  
     private int Mutiplier = 0;  
     private AndroidJavaObject    mCal = null;  
     // Use this for initialization  
     void Start ()   
     {          
     //產生NumberAdder物件  
         this.mCal = new AndroidJavaObject(&quot;com.calculator.numberincreasing.NumberAdder&quot;);  
     //建立傳入參數陣列  
         object[] arglist = new object[2];  
         arglist[0] = (object)this.Org;  
         arglist[1] = (object)this.factor;  
     //呼叫方法，並取得回傳值  
         this.Added = this.mCal.Call&amp;lt;int&amp;gt;(&quot;Add&quot;, arglist);          
         this.mCal = new AndroidJavaObject(&quot;com.calculator.numberincreasing.NumberMultipler&quot;);          
         arglist[0] = (object)this.Org;  
         arglist[1] = (object)this.Mutiple;  
         this.Mutiplier = this.mCal.Call&amp;lt;int&amp;gt;(&quot;Multiple&quot;, arglist);  
     }  

//輸出測試結果
     void OnGUI()  
     {  
         GUI.Label(new Rect(100.0f, 100.0f, 100.0f, 50.0f), string.Format(&quot;Org = {0}\nAdded = {1}\nMultipled = {2}&quot;, this.Org, this.Added, this.Mutiplier));  
     }  
 }  
&lt;/pre&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp;如果要使用JAR檔內的類別，需要透過&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AndroidJavaObject.html&quot; target=&quot;_blank&quot;&gt;AndroidJavaObject&lt;/a&gt;來產生目標類別的物件。
在產生AndroidJavaObject時所傳入的名稱為Package名稱與Class名稱的合稱。(Package = com.calculator.numberincreasing, Class = NumberAdder. Package.Class = com.calculator.numberincreasing.NumberAdder)
之後再使用&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AndroidJavaObject.Call.html&quot; target=&quot;_blank&quot;&gt;AndroidJavaObject.Call()&lt;/a&gt;來操作指定的函式。
&lt;br /&gt;
&lt;br /&gt;
III.產生apk檔，並安裝到Android裝置內。&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; 透過上述方式，就可以把一些方法封裝到其它的Package內。然後就可以給其它的專案使用。&lt;br /&gt;
&amp;nbsp; 如有需要使用到一些Android的API，也可以透過Plugins的方式來使用。&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/7031210782973640110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2013/05/unityplugin-jar.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/7031210782973640110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/7031210782973640110'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2013/05/unityplugin-jar.html' title='[Unity]Plugin建立過程 - JAR'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9BaCgh3xWvKy8Ka9T8hJphpvnfGFBjFVNfzJsCmcvnh1HlQ-PWP6db4H9Q1omXcCYlaCqlTagH2QjJkL-WSR1f1n7j9auyaX8Rjsx2onjPTP-YzRFIPD6G1YrJ_MPYu8Z9HbaUTp8_L4/s72-c/01.png" height="72" width="72"/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-5729024747761609910</id><published>2013-04-17T18:09:00.000+10:00</published><updated>2013-04-17T18:09:48.703+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><title type='text'>[Android]存取External Storage</title><content type='html'>在權限的部分，需在Manifest檔內加入：
&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-xml&quot;&gt;
&amp;lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot; &amp;#47&amp;gt;
&amp;lt;uses-permission android:name=&quot;android.permission.MOUNT_UNMOUNT_FILESYSTEMS&quot; &amp;#47&amp;gt;
&lt;/pre&gt;
前者為設定可讀寫的權限。是必備的。&lt;/br&gt;
後者是設定可掛載或是卸載可移除式儲存裝置。(如沒有加入這個權限，則在進行檔案操作時，會出現&quot;Permission Denied&quot;的錯誤訊息)。&lt;/br&gt;

&lt;/br&gt;
&lt;b&gt;A.之後在進行檔案寫入的動作時&lt;/b&gt;，&lt;/br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.如果是要寫入二進位的資料，可用&lt;a href=&quot;http://docs.oracle.com/javase/1.5.0/docs/api/java/io/FileOutputStream.html&quot;&gt;FileOutputStream.write()&lt;/a&gt;直接寫出檔案。
&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-java linenums&quot;&gt;
private void WriteData(String Data)  
{
//Check the state of storage
    if( !Environment.MEDIA_MOUNTED.equals((Environment.getExternalStorageState())) ) {  
        Log.d(&quot;WriteData&quot;, &quot;--SDCard has been removed.--&quot;);  
        return;  
    }  

    try  
    {  
    //Get the path of root folder  
        File rootDir = Environment.getExternalStorageDirectory();  

    //Create a output stream object  
        FileOutputStream outStream = new FileOutputStream(new File(rootDir.getPath(), &quot;IOTestFile.dat&quot;));  

    //Write Data  
        byte[] buffer = new byte[BUFFER_SIZE];  
        buffer[0] = 0x30;  
        buffer[1] = 0x31;  
        buffer[2] = 0x32;  
        buffer[3] = 0x33;  
        buffer[4] = 0x34;  
        outStream.write(buffer, 0, 5);  

    //Flush it  
        outStream.flush();  

    //Close self  
        outStream.close();  

    }catch(Exception e){  
        Log.d(&quot;--WriteData--&quot;, e.getMessage());  
    }          
}  
&lt;/pre&gt;
要注意的是，使用FileOutputStream時，要把FileOutputStream放到try...catch()內。
&lt;a href=&quot;http://developer.android.com/reference/android/os/Environment.html&quot;&gt;Environment.getExternalStorageDirectory()&lt;/a&gt;可以取得到目前External storage所在的路徑。
&lt;/br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.如果是要寫入純文字檔，可用FileOutputStream與&lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/io/OutputStreamWriter.html&quot;&gt;OutputStreamWriter.append()&lt;/a&gt;來將資料寫入檔案內。
&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-java linenums&quot;&gt;
private void WriteDataWithOutputStreamWriter()  
{  
    try  
    {  
        String FuncName = &quot;WriteDataWithOutputStreamWriter&quot;;  

    //Check the SDCard state  
        if(!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))  
        {  
            Log.d(&quot;WriteDataWithOutputStreamWriter&quot;, &quot;======== External SD Card not mounted ===========&quot;);  
            return;  
        }  

    //Get the path of the root folder  
        File rootDir = Environment.getExternalStorageDirectory();  

    //Create file object  
        File FileContent = new File(String.format(&quot;%s/%s/IOTestFile.dat&quot;, rootDir.getParent(), rootDir.getName()));  

        if(!FileContent.createNewFile())  
        {  
            Log.d(FuncName, &quot;Cannot create file&quot;);  
        }  
        Log.d(&quot;WriteDataWithOutputStreamWriter&quot;, String.format(&quot;======= Target Path = %s ============&quot;, FileContent.getPath()));  

    //Create a output stream object  
        FileOutputStream outStream = new FileOutputStream(FileContent);  

    //Create a output stream writer  
        OutputStreamWriter streamWriter = new OutputStreamWriter(outStream);  

    //write data  
        streamWriter.append(&quot;lalalala&quot;);  

    //close writer  
        streamWriter.close();  

    //close output stream object  
        outStream.close();  
    }catch(Exception e){  
        Log.d(&quot;--WriteDataByOutputStreamWriter--&quot;, e.getMessage());  
    }
}  
&lt;/pre&gt;
&lt;b&gt;B.如果是要讀取檔案，則可以用：&lt;/b&gt;&lt;/br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.讀取二進位檔的內容，則可用&lt;a href=&quot;http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html&quot;&gt;FileInputStream&lt;/a&gt;來取得資料即可。
&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-java linenums&quot;&gt;
private String ReadData()  
{  
    try  
    {  
    //Get the path of root folder  
        File rootDir = Environment.getExternalStorageDirectory();  

    //Create a input Stream Object  
        FileInputStream inStream = new FileInputStream(new File(rootDir.getPath(), &quot;IOTestFile.dat&quot;));  

    //Load the data from target  
        byte[] buffer = new byte[BUFFER_SIZE];  
        int DataLen = inStream.read(buffer);  
        if(DataLen == -1)  
        {  
            Log.d(&quot;ReadData&quot;, &quot;========= Reading Data has problem. ==================&quot;);  
            throw new IOException(&quot;Reading Data has problem.&quot;);  
        }  

        inStream.close();  

    //Show data  
        TextView text = (TextView)findViewById(R.id.editText1);  
        String OutText = &quot;&quot;;  
        for(int i = 0 ; i &amp;lt; 5 ; i++)  
        {  
            Log.d(&quot;ReadData&quot;, String.format(&quot;--------- Data(%x) has been loaded from %s -------------&quot;, buffer[i], rootDir.getPath()));  
            OutText += String.format(&quot;%x&quot;, buffer[i]);  
        }  

        text.setText((CharSequence)OutText);
    }catch(Exception e){  
        Log.d(&quot;--ReadData--&quot;, e.getMessage());  
    }  
    return &quot;&quot;;  
}  
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/5729024747761609910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2013/04/androidexternal-storage.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/5729024747761609910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/5729024747761609910'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2013/04/androidexternal-storage.html' title='[Android]存取External Storage'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-1595050183841798055</id><published>2012-11-27T11:49:00.000+10:00</published><updated>2012-11-27T11:49:43.218+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="MFC"/><title type='text'>[CListCtrl]拖曳檔案至List上方</title><content type='html'>如要操作行為正確，此方法需先繼承CListCtrl之後，並改寫OnDropFiles()。&lt;br /&gt;
&lt;br /&gt;
如不太強調行為正確，則改寫Dialog的OnDropFiles()也可以。&lt;br /&gt;
&lt;br /&gt;
這邊選用偷懶的方式，直接改寫Dialog的OnDropFiles()。&lt;br /&gt;
&lt;br /&gt;
1.先要將Dialog(CListCtrl)的Accept File屬性打開，這樣才能將檔案拖到Dialog上面並丟下。&lt;br /&gt;
&lt;br /&gt;
2.加入自定訊息的&lt;br /&gt;
&lt;br /&gt;
3.ON_WM_DROPFILES()&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-cpp linenums&quot;&gt;
enum eMyListCtrl{ WM_USER_CHANGE_LIST = WM_APP + 0x0100 };  
   
 ON_MESSAGE( WM_USER_CHANGE_LIST, OnDropFilesToList )  
   
 void CFileSearchDlg::OnDropFiles(HDROP hDropInfo)  
 {  
   // TODO: Add your message handler code here and/or call default  
    char  cFilePathName[_MAX_PATH] = {0};  
    UINT nNumOfFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0); //文件的个数  
    for ( UINT nIndex=0 ; nIndex&amp;amp;lt; nNumOfFiles; ++nIndex )  
    {  
      DragQueryFile(hDropInfo, nIndex, cFilePathName, _MAX_PATH); //得到文件名  
      // 把得到的文件名传给父窗口  
      LPARAM lParam = (LPARAM)cFilePathName;  
      //GetParent()-&amp;gt;SendMessage(WM_USER_CHANGE_LIST,0,lParam);  
      this-&amp;gt;SendMessage(WM_USER_CHANGE_LIST,0,lParam);  
    }  
   
   CDialog::OnDropFiles(hDropInfo);  
 }  
   
 LRESULT CFileSearchDlg::OnDropFilesToList(WPARAM wParam, LPARAM lParam)  
 {  
   //m_wndListCtrl.DeleteAllItems();  
   char * cFilePath = (char *)lParam;// 得到拖放文件的路径  
   
   //Check is dir or File Path  
   this-&amp;gt;SearchFileList(cFilePath);  
   
   return true;  
 }  
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/1595050183841798055/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2012/11/clistctrllist.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/1595050183841798055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/1595050183841798055'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2012/11/clistctrllist.html' title='[CListCtrl]拖曳檔案至List上方'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-8343787820894464793</id><published>2012-11-21T18:03:00.003+10:00</published><updated>2012-11-21T18:03:36.432+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Animation"/><category scheme="http://www.blogger.com/atom/ns#" term="AnimationState"/><category scheme="http://www.blogger.com/atom/ns#" term="Unity(3.5.6f4)"/><title type='text'>[Unity]AnimationState</title><content type='html'>參考資料：&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AnimationState.html&quot; target=&quot;_blank&quot;&gt;AnimationState&lt;/a&gt;&lt;br /&gt;
Unity版本：3.5.6f4&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 一般在控制AnimationClip播放時，都會使用Animation類別來控制。但如果想要控制播放速度時，確沒有介面可以控制。所以如果要變更播放各個AnimationClip的播放速度的話，就需要直接操作Animation內所儲存的AnimationStates。底下就針對AnimationState的各個屬性與操作介面來進行測試。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;b&gt;I.屬性：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;1.enabled：&lt;/b&gt;&lt;i&gt;(bool)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 此屬性是用來控制目前所對應的AnimationClip能不能進行播放。所以在Animation Clip播放時，將AnimationState.enabled設為false時，時間軸就會停止在當下的時間。之後再把AnimationState.enabled設為true時，時間軸就會從目前停止的時間繼續往下播放。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;2.weight：&lt;/b&gt;&lt;i&gt;(float)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 目前文件寫的看不懂，所以先跳過。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;3.wrapMode：&lt;/b&gt;&lt;i&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/WrapMode.html&quot; target=&quot;_blank&quot;&gt;WrapMode&lt;/a&gt;)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AnimationClip的播放模式，可以參考&lt;a href=&quot;http://totsi04.blogspot.tw/2012/11/unityanimation-warpmode.html&quot; target=&quot;_blank&quot;&gt;[Unity]Animation WarpMode&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;4.time：&lt;/b&gt;&lt;i&gt;(float)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 動畫的播放時間軸，一般是從0到無限大。可以透過強制指定時間軸來讓動畫的時間軸移動到指定的時間，但此時動畫物件本身並不會到達指定時間的狀態，也就是動畫物件會停留在上次停止的位置。當開始播放動畫的時候，就會從指定的時間開始播放。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;5.normalizedTime：&lt;/b&gt;&lt;i&gt;(float)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; normalize的動畫時間。此屬性為0到1。0.5代表動畫的時間的中點。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;6.speed：&lt;/b&gt;&lt;i&gt;(float)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 動畫播放速度，此屬性等於1時，就是正常播放。如要反向播放的話，就只要給定負值就好。為了達到反向播放的效果，也要注意到WrapMode的問題，可以參考&lt;a href=&quot;http://totsi04.blogspot.tw/2012/11/unityanimation-warpmode.html&quot; target=&quot;_blank&quot;&gt;[Unity]Animation WarpMode&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;7.normalizedSpeed：&lt;/b&gt;&lt;i&gt;(float)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; normalize的播放速度，一般是做為在兩個動畫間做同步播放使用。根據官方的說法，此屬性會比&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/Animation.SyncLayer.html&quot; target=&quot;_blank&quot;&gt;Animation.SyncLayer()&lt;/a&gt;易於使用。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;8.length：&lt;/b&gt;&lt;i&gt;(float)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Animation Clip的總播放時間，單位為秒。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;9.layer：&lt;/b&gt;&lt;i&gt;(int)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 此屬性用來設定AnimationClip播放時的層級，層級會影響到計算動畫播放時的權重值。越高層級的AnimationClip在計算最後繪製權重時，比較可以優先得到自已所預期需要的權重值。而低層級的AnimationClip僅能使用高層級所不需用到的權重值，換句話說，也就是低層級的僅能撿高層級剩下的來用。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;10.clip：&lt;/b&gt;&lt;i&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AnimationClip.html&quot; target=&quot;_blank&quot;&gt;AnimationClip&lt;/a&gt;)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 要用來播放的AnimationClip。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;11.name：&lt;/b&gt;&lt;i&gt;(String)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; AnimationClip的名稱。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;12.blendMode：&lt;/b&gt;&lt;/span&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AnimationBlendMode.html&quot; target=&quot;_blank&quot;&gt;AnimationBlendMode&lt;/a&gt;)&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 動畫的繪製模式。可參考 &amp;nbsp; &amp;nbsp; 。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;b&gt;II.操作介面：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;1.AddMixingTransform(Transform mix, bool recursive = true)：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 把要有相同的動畫效果的GameObject.transform加到AnimationState內，這樣就可以使用同一個動畫效果套用到不同的GameObject上。這樣可以減少AnimationClip的製作數量。&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; recursive設為true時，代表所有混合的transform的子物件都將會被以同樣的方式播放動畫。&lt;br /&gt;
(目前未測試成功)&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;2.RemoveMixingTransform(Transform mix)：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 把加到AnimationState內的GameObject.transform移除。</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/8343787820894464793/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2012/11/unityanimationstate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/8343787820894464793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/8343787820894464793'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2012/11/unityanimationstate.html' title='[Unity]AnimationState'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-1483135770380354703</id><published>2012-11-20T11:34:00.000+10:00</published><updated>2012-11-27T12:52:14.234+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Animation"/><category scheme="http://www.blogger.com/atom/ns#" term="Animation Clip"/><category scheme="http://www.blogger.com/atom/ns#" term="Unity(3.5.6f4)"/><title type='text'>[Unity]Animation WarpMode</title><content type='html'>參考資料：&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/Animation-wrapMode.html&quot; target=&quot;_blank&quot;&gt;Animation.wrapMode&lt;/a&gt;、&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/WrapMode.html&quot; target=&quot;_blank&quot;&gt;WrapMode&lt;/a&gt;。&lt;br /&gt;
Unity版本：3.5.6f4&lt;br /&gt;
&lt;br /&gt;
在Unity內Animation的WrapMode可以透過Script來變更。以下針對各個參數進行說明：&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;1.WrapMode.Default：&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 直接拿Amination Clip內設定的wrapMode來進行動畫播放。預設的wrapMode為WrapMode.Once。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;2.WrapMode.Once：&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 當動畫時間軸到達Animation Clip終點時，正在播放中的Animation Clip會被自動的停止播放，並且時間軸會被重設回Animation Clip的一開始。&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;不過當Animation Clip是從終點反向播放到起點時，雖然在播放到起點時會也會被自動停止，但是時間軸並不會被重置回終點，而是留在起點。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;3.WrapMode.Loop：&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 當動畫時間軸到達Animation Clip的終點時，時間軸會又回到起點的位置，並且繼續播放動畫。如果將播放模式設為反向時(即將Animation[ClipName].speed設為負值)，則會從反向播放動畫，而播放的起點與終點都會跟正向播放時相反。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Note:&lt;/b&gt;根據官方的說法，將&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AnimationState-speed.html&quot; target=&quot;_blank&quot;&gt;AnimationState.speed&lt;/a&gt;設為負值時，Animation Clip就會被反向播放(A negative playback speed will play the animation backwards.)。&lt;strike&gt;但目前測試由3dMax匯出的Animation以及使用Unity Animation所做出的Clip，在播放移動Animation時，把AnimationState.speed設為-1，播放的結果是物件直接跳到起始位置，並沒在從終點移動到起點位置。這邊還需要再確認問題點在那邊。&lt;/strike&gt;&lt;br /&gt;
&lt;br /&gt;
Note(2012/11/20)：&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 今找到原因了，原先測試時，只有變更AnimationState.speed，而沒有去變更AnimationState.time。所以播放時，時間軸就已經在0的位置了，也因此看不到動畫做動。&lt;b&gt;如要反向播放動畫則需變更AnimationState.Speed為負值以及設定AnimationState.time不為起點。&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;4.WrapMode.PingPong：&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 當動畫時間軸到達Animation Clip的終點時，時間軸會在往起點的方向前進。這個動畫效果會使物件重複的在Animation Clip的起點與終點之間來回的播放動畫。對於需要來回反複播放的動畫而言，就可以設定成此狀態。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;5.WrapMode.ClampForever：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 當動畫時間軸到達Animation Clip的終點時，時間軸將會停止在Animaiton Clip的終點，且&lt;b&gt;動畫播放狀態依然是播放中&lt;/b&gt;，也就是Animation不會停止Animation Clip的動畫播放。而如果設定為反向播放時，時間軸到達起點時，也一樣會停止在起點，且Animaiton Clip也是在播放中的狀態。也因此，此設定會使Animation Clip只播放一次。&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 根據官方文件的說法，這個設定可以用在播放時間軸到達終點後不打算結束的Additive Animation上。根據測試的結果為，&lt;b&gt;&lt;span style=&quot;color: blue;&quot;&gt;動畫物件是會停在時間軸的結束狀態下，但AnimationStates[].time還是會持續的增加或是減少&lt;/span&gt;&lt;/b&gt;(依據設定的播放時間值)。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 在Animation以及Animation Clip上都有WrapMode的屬性，而透過Script去設定時，卻有些許的不同。&lt;span style=&quot;color: blue;&quot;&gt;對於wrapMode這個屬性，在Animation本身上，是可以在播放中就去設定，而且會立即生效&lt;/span&gt;&lt;span style=&quot;color: red;&quot;&gt;；但是當Animation Clip正在播放中的時後，AnimationClip.wrapMode是不能被變更的(唯讀狀態)。&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;以下為操作測試：&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
I.在Script內去變更Animation.wrapMode時，WrapMode會立即的套用在Animation Clip的播放上(如果是透過Inspector來變更，則WrapMode不會立即的套用在Animation Clip的播放上)，但Animation Clip.warpMode還是保持原本的設定。&lt;br /&gt;
&lt;br /&gt;
例如：Animation.wrapMode原本設定為WrapMode.Once，Animation Clip.wrapMode也設定為WrapMode.Once。在Animation.Play()之後，且Animation Clip播放完畢之前，將&amp;nbsp;Animation.wrapMode改為WrapMode.PingPong。則此時看到的動畫效果就變成來回播放，但是Animation Clip.wrapMode還是依舊為WrapMode.Once。&lt;br /&gt;
&lt;br /&gt;
II.在Script內去變更Animation Clip.wrapMode時，WrapMode會立即套用到Animation Clip.wrapMode，但是並不會影響到正在播放的Animation。&lt;br /&gt;
&lt;br /&gt;
例如：Animation.wrapMode原本設定為WrapMode.Once，Animation Clip.wrapMode也設定為WrapMode.Once。在Animation.Play()之後，且Animation Clip播放完畢之前，將&amp;nbsp;Animation.wrapMode改為WrapMode.PingPong。則此時看到的動畫還是播完後就停止了，但此時又再重新播放動畫的話，動畫效果還是一樣只播一次。不過在Animation Clip.wrapMode的設定上，是有被變更為WrapMode.PingPong。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;例外原因：&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 會出現上面的狀況是因為Animation是透過AnimationState來控制動畫的播放。根據目前的測試，在編輯模式下，AnimationStates是一個空的陣列(圖1.)。當啟用Play模式時，Animation會把在Animations內所指定的Animation Clip的name以及wrapMode新增到AnimationStates內(圖2.)(Animation Clip的設定請參考圖3.)。由這邊看出Unity看起來是在Animation初始化的時候取得AnimationClip.wrapMode，並加到AnimationState內。&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9J5d-gaO32RTHzuAT0dt9-_Ce2SV-h9URf5Rsjo_8PFWg9mUv5ppYgQhHcKZI3rPrENK81rEcQP2n_WMOKxumsV2IkNBNDnRNaabWNmBF_u8oHydohEQkiqbdYuTh4T9oYY3cQyqMqq0/s1600/AnimationState_Editor.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;164&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9J5d-gaO32RTHzuAT0dt9-_Ce2SV-h9URf5Rsjo_8PFWg9mUv5ppYgQhHcKZI3rPrENK81rEcQP2n_WMOKxumsV2IkNBNDnRNaabWNmBF_u8oHydohEQkiqbdYuTh4T9oYY3cQyqMqq0/s320/AnimationState_Editor.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;b&gt;圖1.編輯模式下的Animation States&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCJNiPnHuvwHFjZk_m4x_uLtoyiEf-w9RrY1buRhUR4V9Tv74TNOynUV4Phs3GTiFxKn3aP-Bs4zD-9qTBwSU7qATGAlJ00OfBTyfDL_lWA0200L673jJykvsP8EJY0nZqzm2dTSmZT3M/s1600/AnimationState_Play.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCJNiPnHuvwHFjZk_m4x_uLtoyiEf-w9RrY1buRhUR4V9Tv74TNOynUV4Phs3GTiFxKn3aP-Bs4zD-9qTBwSU7qATGAlJ00OfBTyfDL_lWA0200L673jJykvsP8EJY0nZqzm2dTSmZT3M/s320/AnimationState_Play.png&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;b&gt;圖2.Play&lt;/b&gt;&lt;b&gt;模式下的Animation States&lt;/b&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtME0N_AAhZKO8uJzmoT622CI9l7J6bP-xKw_LXN59R5BoDjMtdmNEhryTZKalIA4-FUiFiWMuYp67QsbtE1Ha8427cXU2ak8wP0ZCe7iCwAYsIim_bng_zHfXjBig5ey5fGjY7uvtluE/s1600/AnimationState_ClipSet.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;163&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtME0N_AAhZKO8uJzmoT622CI9l7J6bP-xKw_LXN59R5BoDjMtdmNEhryTZKalIA4-FUiFiWMuYp67QsbtE1Ha8427cXU2ak8wP0ZCe7iCwAYsIim_bng_zHfXjBig5ey5fGjY7uvtluE/s320/AnimationState_ClipSet.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;b&gt;圖3.AnimationClip的設定&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 在上述的狀況下，變更Animation Clip.wrapMode(圖4.)，此時卻發現一開始加到AnimationStates的wrapMode卻沒有變更。所以由此推測，這邊的wrapMode是從AnimationClip.wrapMode複製來的，而不是取得參考。這也可以指出，為什麼在Animation沒有重新取得AnimationClip時，播放的結果總是不同於設定的值。所以之後再怎麼變更AnimacionClip.wrapMode，Animatoin也不可能知到目前指定的AnimationClip已經有任何的變化。&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJCJpWkqT1z1JO5LMZ0V46KpkyvEHJ9TcKPoLorQMWRqqfFbsEXSYH8uC7UVbtb-bU4BJZugEAbxl2WUuXFdT456qTm7egk5itzGIpNBof8sa1ANl0bQe0yukqA12BR5UiWNVJ2asOP-E/s1600/Anime_ChangeWrapMode.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJCJpWkqT1z1JO5LMZ0V46KpkyvEHJ9TcKPoLorQMWRqqfFbsEXSYH8uC7UVbtb-bU4BJZugEAbxl2WUuXFdT456qTm7egk5itzGIpNBof8sa1ANl0bQe0yukqA12BR5UiWNVJ2asOP-E/s1600/Anime_ChangeWrapMode.png&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilx-U4d_mbk39lQQYVpeyJ9cGGOjHZsMHV9McsWYiYa3WeUH0s_SA3BBO52UFj_WXyGjNjmIhhD7MTBgEMrh56wFoU6RjVYMDWTolK5fIScreCeMjqDsLXPESTnEbhbWJWOJ2SliRENxs/s1600/Anime_ChangeWM_Animation.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilx-U4d_mbk39lQQYVpeyJ9cGGOjHZsMHV9McsWYiYa3WeUH0s_SA3BBO52UFj_WXyGjNjmIhhD7MTBgEMrh56wFoU6RjVYMDWTolK5fIScreCeMjqDsLXPESTnEbhbWJWOJ2SliRENxs/s320/Anime_ChangeWM_Animation.png&quot; width=&quot;243&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;b&gt;圖4.變更AnimationClip.wrapMode &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 圖5.[圖4.]狀態下的Animation資訊&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;解決方案：&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
i.在使用Unity Editor的模式下，僅需再重新Play Game Mode，就可以使用到變更後的WrapMode。&lt;br /&gt;
&lt;br /&gt;
ii.在使用編譯後的執行檔時，有三種方法可以使用變更後的WrapMode：&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;1.重新載入場景。&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;2.刪除目前GameObject所持有的Animation元件，並再重新加入Animation元件與Animation Clip&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 後。如要用這方法，則需在刪除Animation後的下一個Frame才可以再新增Animation元件，&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: red;&quot;&gt;不然Unity會跳出物件還存在且不可重複加入的錯誤訊息&lt;/span&gt;。原因是&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/Object.Destroy.html&quot; target=&quot;_blank&quot;&gt;Object.Destroy()&lt;/a&gt;所說的&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;「物件的刪除總是在Update loop結束之後以及rendering之前發生」。&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp;3.直接將新的Animation Clip.wrapMode指定給Animation[Animation Clip.name].wrapMode。&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;結論：&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
1.在Inspector修改Animation.wrapMode並不會立刻套用到目前的播放上。(AnimaitonStates不會被立即變更)&lt;br /&gt;
&lt;br /&gt;
2.透過Script修改Animation.wrapMode會立即套用到所有的AnimationClip(包含目前的播放)在Animation Component內的wrapMode上。(AnimationStates會被立即變更)&lt;br /&gt;
&lt;br /&gt;
3.變更過的AnimationClip.wrapMode需要Animation Component進行重載後，才會更新到AnimaitonStates。&lt;br /&gt;
&lt;br /&gt;
4.播放中的Animation Clip是不能進行wrapMode的變更。</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/1483135770380354703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2012/11/unityanimation-warpmode.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/1483135770380354703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/1483135770380354703'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2012/11/unityanimation-warpmode.html' title='[Unity]Animation WarpMode'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9J5d-gaO32RTHzuAT0dt9-_Ce2SV-h9URf5Rsjo_8PFWg9mUv5ppYgQhHcKZI3rPrENK81rEcQP2n_WMOKxumsV2IkNBNDnRNaabWNmBF_u8oHydohEQkiqbdYuTh4T9oYY3cQyqMqq0/s72-c/AnimationState_Editor.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-6820566858441770018</id><published>2012-11-16T16:21:00.000+10:00</published><updated>2012-11-27T12:44:18.294+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Animation"/><category scheme="http://www.blogger.com/atom/ns#" term="Unity(3.5.6f4)"/><title type='text'>[Unity]Animation Component - Attributes</title><content type='html'>參考資料：&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/Animation.html&quot; target=&quot;_blank&quot;&gt;Scripting &amp;gt; Runtime Classes &amp;gt; Animation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;跟據官方的說法，這個元件是用來做動畫播放使用。而整個動畫系統是利用「&lt;span style=&quot;color: blue;&quot;&gt;權重&lt;/span&gt;」的方式來進行動畫的播放。相關內容可以參考&lt;a href=&quot;http://docs.unity3d.com/Documentation/Manual/AnimationScripting.html&quot; target=&quot;_blank&quot;&gt;Unity Manual &amp;gt; Animation Scripting&lt;/a&gt;。底下針對Animation所提供的屬性來進行說明。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;1.clip&lt;/b&gt;：&lt;i&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AnimationClip.html&quot; target=&quot;_blank&quot;&gt;Animation Clip&lt;/a&gt;)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 在沒有指定播放的clip時進行播放時，所會播放的Animation clip。即在Script內呼叫Animation.Play()時，Animation Component就會播放此組clip。在Inspector底下所看到的屬性如&lt;b&gt;圖.1&lt;/b&gt;的紅框框選處。&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjySXgS3Ehh_P3hZzfL6KOlApN0IOjiVu6VyF9NR0piBi7Oh0F0mZMTAVrhllqXooodr5dVynTyLDo9GGMCd3Buve6km17axGXiosbqc8f6p2qY9ZU4_aBZtHH-y87fwz70ZJoLLYYhWHM/s1600/desc.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;244&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjySXgS3Ehh_P3hZzfL6KOlApN0IOjiVu6VyF9NR0piBi7Oh0F0mZMTAVrhllqXooodr5dVynTyLDo9GGMCd3Buve6km17axGXiosbqc8f6p2qY9ZU4_aBZtHH-y87fwz70ZJoLLYYhWHM/s640/desc.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;b&gt;圖1.Animation設定介面&lt;/b&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;2.playAutomatically：&lt;/b&gt;&lt;i&gt;(bool)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 這個屬性是用來決定在GameObject啟動(Active)時，是否要播放預設的Animation Clip。也就是此值為true時，Animation System則會在GameObject設為啟動(Active)之後，自動播放Animation.clip的動畫內容。在Inspector底下所看到的屬性如&lt;b&gt;圖.1&lt;/b&gt;的綠框框選處。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;3.wrapMode：&lt;/b&gt;&lt;i&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/WrapMode.html&quot; target=&quot;_blank&quot;&gt;WrapMode&lt;/a&gt;)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 此屬性是用來決定當Animation Clip播放完畢時，接下來要做何種處理。可以參考&lt;a href=&quot;http://totsi04.blogspot.tw/2012/11/unityanimation-warpmode.html&quot; target=&quot;_blank&quot;&gt;[Unity]Animation WarpMode&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;4.isPlaying：&lt;/b&gt;&lt;i&gt;(bool)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 此屬性可用來判斷Animation Clip是否已經被播放完畢。當此屬性為true時，即是指定的Animation Clip還在播放中；反之為false時，則代表指定的Animation Clip已經停止播放了。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;5.this[string name]：&lt;/b&gt;&lt;i&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AnimationState.html&quot; target=&quot;_blank&quot;&gt;AnimationState&lt;/a&gt;)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 此Indexer可以透過Animation Clip的名稱來取得其所用到的AnimationState。因此如有需要修改AnimationState的屬性時，就可以使用此屬性。說明測試也可以參考&lt;a href=&quot;http://totsi04.blogspot.tw/2012/11/unityanimationstate.html&quot; target=&quot;_blank&quot;&gt;[Unity]AnimationState&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;6.animatePhysics：&lt;/b&gt;&lt;i&gt;(bool)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 這個屬性是用來設定Animation播放時，會不會受到物理引擎的影響。當此屬性設為true時，Animation Clip播放時，就會被加到物理引擎內進行計算。但如要使此設定有效時，還必需先在要播放Animation Clip的GameObject上加上&lt;a href=&quot;http://docs.unity3d.com/Documentation/Components/class-Rigidbody.html&quot; target=&quot;_blank&quot;&gt;RigidBody&lt;/a&gt;，並設定成會受物理引擎影響。在Inspector底下所看到的屬性如&lt;b&gt;圖1.&lt;/b&gt;的黃框框選處。&lt;br /&gt;
&lt;br /&gt;
Note:目前測試在播放水平移動的動畫時，再加上重力影響時，高度座標的的確是有所改變。&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;但其變化量比無播放動畫時的狀況還要來的小很多。&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;7.cullingType：&lt;/b&gt;&lt;i&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/AnimationCullingType.html&quot; target=&quot;_blank&quot;&gt;AnimationCullingType&lt;/a&gt;)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 跟據官的說法，當culling被起動時(也就是設定不是AnimationCullingType.AlwaysAnimate)，Unity會在animation不會被使用者看到時，自動的停止AnimatoinClip的播放。因此這個設定是用來節省效能消耗。當動畫元件被culled的時候，AnimatoinState、Event或是Sample Animation(可以參考&lt;a href=&quot;http://answers.unity3d.com/questions/46869/animationsample-usage.html&quot; target=&quot;_blank&quot;&gt;animation.sample() usage&lt;/a&gt;)都不會有做用。在Inspector底下所看到的屬性如&lt;b&gt;圖1.&lt;/b&gt;的紫框框選處。(不過目前測試沒有成功的試出來。)&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;&lt;b&gt;8.localBounds：&lt;/b&gt;&lt;i&gt;(&lt;a href=&quot;http://docs.unity3d.com/Documentation/ScriptReference/Bounds.html&quot; target=&quot;_blank&quot;&gt;Bounds&lt;/a&gt;)&lt;/i&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; 此屬性為Animation的動畫元件(animation component)在區域座標(local space)下的Axis-aligned minimum bounding box(AABB)。跟據官方的說法，此屬性在預設的條件下，是跟據動畫狀態(animation state，也就是所附加的Animation Clip)來計算的。而使用者也可以透過重新指定數值來變更目前的localBounds。&lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; 如有要數值更改回原設定值，就僅需將Animation.cullingType設定為AnimationCullingType.BasedOnClipBounds即可。在Animation.cullingType沒有設定為AnimationCullingType.BasedOnClipBounds或是AnimationCullingType.BasedonUse的時候，此屬性是沒有被定義的。然而當Animation.localBounds被設定時，系統就會自動將Animation.cullingType設定為AnimationCullingType.BasedOnUserBounds。</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/6820566858441770018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2012/11/unityanimation-component-attributes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/6820566858441770018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/6820566858441770018'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2012/11/unityanimation-component-attributes.html' title='[Unity]Animation Component - Attributes'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjySXgS3Ehh_P3hZzfL6KOlApN0IOjiVu6VyF9NR0piBi7Oh0F0mZMTAVrhllqXooodr5dVynTyLDo9GGMCd3Buve6km17axGXiosbqc8f6p2qY9ZU4_aBZtHH-y87fwz70ZJoLLYYhWHM/s72-c/desc.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1721523466657532879.post-9061077937272949135</id><published>2012-11-09T16:06:00.000+10:00</published><updated>2016-03-19T18:39:19.445+10:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blogger Tool"/><title type='text'>使用Google Code Prettify來顯示程式碼</title><content type='html'>這邊網路上可以找到不少的參考資料，但為了自己方便尋找，所以就根據參考來源，備份一份資料。&lt;br /&gt;
&lt;br /&gt;
參考來源：&lt;br /&gt;
1.&lt;a href=&quot;http://uzo9.blogspot.tw/2012/08/blogger-google-code-prettify.html&quot;&gt;優力歐不眠夜[在 blogger 中加入 google-code-prettify]&lt;/a&gt;&lt;br /&gt;
2.&lt;a href=&quot;http://code.google.com/p/google-code-prettify/&quot;&gt;Google-Code-Prettify&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;I.設定：&lt;/b&gt;&lt;br /&gt;
使用方式如下：&lt;br /&gt;
1.登入網誌後台後選擇『範本』-&amp;gt;『修改HTML』&lt;br /&gt;
&lt;br /&gt;
2.在HTML內找到&amp;lt;/head&amp;gt;，並將下列程式碼貼在&amp;lt;/head&amp;gt;的前面。
&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-html&quot;&gt;&amp;lt;link href=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;&amp;gt;&amp;lt;/link&amp;gt;
&amp;lt;script src=&quot;http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
3.然後在body標籤內加上onload=&#39;prettyPrint()&#39;。&lt;br /&gt;
(參考資料是利用&amp;lt;script&amp;gt;prettyPrint();&amp;lt;/script&amp;gt;;&amp;nbsp;)&lt;br /&gt;
&lt;br /&gt;
4.存檔後，就可以用了。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;II.如何使用：&lt;/b&gt;&lt;br /&gt;
之後如果在文章內需要貼程式碼時，就需要在HTML模式下，加入下面的語法。&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-html&quot;&gt;&amp;lt;pre class=&quot;prettyprint lang-*&quot;&amp;gt;
//要顯示的文字
&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
「*」表示要用來顯示的語言類型，定義請參考&lt;a href=&quot;http://google-code-prettify.googlecode.com/svn/trunk/README.html&quot;&gt;How do I specify the language of my code?&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;III.實作範例：&lt;/b&gt;&lt;br /&gt;
用起來的感覺會像是底下這樣（用C++作範例)&lt;br /&gt;
[HTML語法]&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-html&quot;&gt;&amp;lt;pre class=&quot;prettyprint lang-cpp&quot;&amp;gt;
class MyClass
{
    private:
        int Counter;
        std::vector&lt;b&gt;&lt;i&gt;&amp;amp;lt&lt;/i&gt;&lt;/b&gt;;int&lt;b&gt;&lt;i&gt;&amp;amp;gt&lt;/i&gt;&lt;/b&gt;; mCountList;

    public:
        MyClass(void);
        
    public:
        void Show(void);
}
&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
[顯示畫面]&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-cpp&quot;&gt;class MyClass
{
    private:
        int Counter;
        std::vector&amp;lt;int&amp;gt; mCountList;

    public:
        MyClass(void);
        
    public:
        void Show(void);
}
&lt;/pre&gt;
在要顯示的程式碼內，如果有要用到「&amp;lt;」、「&amp;gt;」，要記得，一定要換成HTML裡面用的「&amp;amp;lt;」及「&amp;amp;gt;」。不然會變成一片空白嚕。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;IV.行號顯示：&lt;/b&gt;&lt;br /&gt;
如果要顯示行號的話，就要在原本的lang後面加上linenums即可。&lt;br /&gt;
[HTML碼]&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-html&quot;&gt;&amp;lt;pre class=&quot;prettyprint lang-cpp linenums&quot;&amp;gt;
class MyClass
{
    private:
        int Counter;
        
    public:
        MyClass(void);
        
    public:
        void Show(void);
}
&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
[顯示畫面]&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-cpp linenums&quot;&gt;class MyClass
{
    private:
        int Counter;
        std::vector&amp;lt;int&amp;gt; mCountList;

    public:
        MyClass(void);
        
    public:
        void Show(void);
}
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
如果在顯示區間內所顯示的程式碼是從原先的程式碼的第100行開始，就可以在linenums後面加上分號以及開頭的行號數值，這樣prettyprint就會把目前這段程式碼應該所在的行號標出來了。&lt;br /&gt;
[HTML碼]&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-html&quot;&gt;&amp;lt;pre class=&quot;prettyprint lang-cpp linenums:100&quot;&amp;gt;
class MyClass
{
    private:
        int Counter;
        
    public:
        MyClass(void);
        
    public:
        void Show(void);
}
&amp;lt;/pre&amp;gt;
&lt;/pre&gt;
&lt;br /&gt;
[顯示畫面]&lt;br /&gt;
&lt;pre class=&quot;prettyprint lang-cpp linenums:100&quot;&gt;class MyClass
{
    private:
        int Counter;
        std::vector&amp;lt;int&amp;gt; mCountList;

    public:
        MyClass(void);
        
    public:
        void Show(void);
}
&lt;/pre&gt;
&lt;br /&gt;
不過目前google code prettify在顯示行號上，就只會顯示(行號 Mod 5 == 0 &amp;amp;&amp;amp;行號 &amp;gt; 0)的行數的行號嚕。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
雖然用起來有點麻煩，但是顯示上看起來還算可以嚕。&lt;br /&gt;
如果覺得上面的方法太麻煩，還有現成的網頁工具可以用，&lt;a href=&quot;http://codeformatter.blogspot.tw/&quot;&gt;Source Code Formatter for Blogger, Blogspot , Blog &amp;amp; Blogging, Format Formatting Tool&lt;/a&gt;。&lt;br /&gt;
好處是，他可以幫你解決符號轉換的問題，也可以顯示每行的行號，缺點是，就沒有顏色了。XD</content><link rel='replies' type='application/atom+xml' href='http://totsi04.blogspot.com/feeds/9061077937272949135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://totsi04.blogspot.com/2012/11/google-code-prettify.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/9061077937272949135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1721523466657532879/posts/default/9061077937272949135'/><link rel='alternate' type='text/html' href='http://totsi04.blogspot.com/2012/11/google-code-prettify.html' title='使用Google Code Prettify來顯示程式碼'/><author><name>Otto Hung (挖土猴)</name><uri>http://www.blogger.com/profile/10893752403725490757</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='30' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjNbC8bWe8rZqrpXaOPWv4VLiwH6lnlkIEx8sUQCEN8CTdB2swSde4PH7L5_p0n10VKi1YKTOXkfDuI3oXfxuTf_rYvj9B2Hy5FxKUJS1kcD7qUgNpE_j3SltuAizfT_Q/s120/avator.jpeg'/></author><thr:total>0</thr:total></entry></feed>