



臺WIN10頻頻死機, 用CrystalDiskInfo睇SSD硬碟温度達66℃. 上次買『M.2散熱』頂住显卡, 索性唔鬼用,今次買薄『M.2散熱』高10mm. 鋁底座,銅翅片.装前66℃. 装後55℃. 睇蒞有作用
- 折散熱底座
- 『SSD硬碟』顶底各貼导熱硅片
- 散熱底座要同粒FLASH貼平
- 修鑼絲
Windows10/Windows11




臺WIN10頻頻死機, 用CrystalDiskInfo睇SSD硬碟温度達66℃. 上次買『M.2散熱』頂住显卡, 索性唔鬼用,今次買薄『M.2散熱』高10mm. 鋁底座,銅翅片.装前66℃. 装後55℃. 睇蒞有作用


之前買雜牌畫板,笔芯浮動,玩咗壹鋪就冇玩, 睇到WACOM畫板做特价, 果斷出手買CTL-672, 畫版簡洁單壹, 相當於係萤幕加触摸. 條USB線畀手機用都歉短, 换條帶磁環USB線.
| https://www.wacom.com/zh-hk/getting-started/one-by-wacom |
| WacomTablet_6.3.46-1.exe |


之前购『Smart Fingerprint Reader指紋鎖』支持Smart-ID, 今你登入网站時免密碼用指紋. 同埋加密本地資料檔
| Smart-ID | 簡述 |
| 密碼管理 | 网站指紋登入 |
| 保密區 | 加密本地資料檔 |
| 指紋維䕶 | 录入指紋 |
| 備份與維䕶 | 備份指紋 |
| Smart-ID |
| http://www.emc.com.tw/products/app/1559/SmartIDInstaller_STD_V42_20210928.zip |
| Smart-ID WebAutoLogin | |
| chrome | https://chrome.google.com/webstore/search/smart-ID |
| firefox | https://addons.mozilla.org/zh-TW/firefox/addon/smart-id-webautologin/ |

2D游戲動画幀, 由多幅關鍵幀(keyFrame) 組成. 逐幀渲染產生動画卡通.『幀動画』亦哎呌『紋理』texture. 将多幅『幀動画』存放係單壹紋理.OpenGL可提高渲染速度, 係显存記憶體1MB年代可能冇用. 事因渲染皆係電脑記憶體運作.
係显存記憶體大幅增長, OpenGL渲染係显存記憶體完成. 减小『紋理』載入量, 單壹紋理存放多幅『幀動画』,可提高渲染速度.
係3D游戲亦可用相同技術提飛渲染效率.
| void zoom_textcoord_model3D(TEXTURE_PTR texture,int index,int size,VECTOR2D_PTR dest,VECTOR2D_PTR sour,int count,int flag) |
| texture | 紋理 |
| index | 關鍵幀索引 |
| size | 關鍵幀寬高解像 |
| dest | 纹理隊列 |
| sour | 原始纹理隊列 |
| count | 纹理頂點量 |
計單元格
| int cell = texture->width / size; |
計索引
| int i = index % cell;// 橫索引 |
| int j = index / cell;// 行索引 |
計缩放率0.0f < zoom < 1.0f
| float zoom = (float)size / (float)texture->width; |
計『幀』偏移.
| float offsetX = (float)zoom * (float)i; |
| float offsetY = (float)zoom * (float)j; |
遍歴UV紋理頂㸃
| for (int p = 0; p < count; ++p){ |
缩細後移動
| dest[p].u = sour[p].u * zoom + offsetX ; |
| dest[p].v = sour[p].v * zoom + offsetY; |
纹理返转
| if (flag & MODEL3D_TEXTURE_FLIP)
dest[p].v = 1 – (sour[p].v * zoom + offsetY);} |


『天幕SKYBOX』指巨立方體, 係內籠貼天幕紋理,『天幕紋理』可能係『地平線』『室內』『宇宙』. 『天幕SKYBOX』原㸃與3D相機位置重合. 係遠睇時正确.
由陸幅紋理『顶』『底』『前』『後』『左』『右』組成. 以前『天幕SKYBOX』紋理分陸幅位圖存檔.
陸幅位圖存係單壹『紋理』效率更高. 将『紋理』平分拾陸等分. 足够擺两組『天幕』紋理. 『日頭』『晚黑』各壹. 似上圖咁.
| 紋理索引:0~15 | 『日頭』 | 『晚黑』 |
| 顶up | 0 | 8 |
| 底dn | 1 | 9 |
| 前ft | 7 | 15 |
| 后bk | 5 | 13 |
| 左lt | 6 | 14 |
| 右rt | 4 | 12 |
定義『天幕SKYBOX』
| typedef struct SKYBOX_TYP { | |
| VECTOR3D pos; | 位置 |
| VECTOR3D rot; | 旋轉 |
| TEXTURE_PTR texture; | 天幕纹理 |
| float size; | 天幕大细 |
| //TEXTURE_REGION region[16]; | 纹理区域 |
| VECTOR3D vertex_array[36] ; | 天幕顶点 |
| VECTOR2D texCoord_array[36] ; | 天幕紋理 |
| }SKYBOX, *SKYBOX_PTR; |
手エ构建『天幕SKYBOX』立方體『3D頂㸃』同『UV紋理』. 正方形以两三角形組成. 紋理左上角[u0, v0], 紋理右下角[u1,v1].天幕大细『size』.
| 天『UV紋理』 | 『xyz頂㸃』 |
| texCoord[0]=[u1, v1] | vertex_array[0]=[-size, size, -size] |
| texCoord[1]=[u0, v1] | vertex_array[1]=[size, size, -size] |
| texCoord[2]=[u0, v0] | vertex_array[2]=[size, size, size] |
| texCoord[3]=[u1, v1] | vertex_array[3]=[-size, size, -size] |
| texCoord[4]=[u0, v0] | vertex_array[4]=[size, size, size] |
| texCoord[5]=[u1, v0] | vertex_array[5]=[-size, size, size] |
| 地『UV紋理』 | 『xyz頂㸃』 |
| texCoord[6]=[u1, v1] | vertex_array[6]=[size, -size, -size] |
| texCoord[7]=[u0, v1] | vertex_array[7]=[-size, -size, -size] |
| texCoord[8]=[u0, v0] | vertex_array[8]=[-size, -size, size] |
| texCoord[9]=[u1, v1] | vertex_array[9]=[size, -size, -size] |
| texCoord[10]=[u0, v0] | vertex_array[10]=[-size, -size, size] |
| texCoord[11]=[u1, v0] | vertex_array[11]=[size, -size, size] |
| 前『UV紋理』 | 『xyz頂㸃』 |
| texCoord[12]=[u0, v0] | vertex_array[12]=[-size, -size, -size] |
| texCoord[13]=[u1, v0] | vertex_array[13]=[size, -size, -size] |
| texCoord[14]=[u1, v1] | vertex_array[14]=[size, size, -size] |
| texCoord[15]=[u0, v0] | vertex_array[15]=[-size, -size, -size] |
| texCoord[16]=[u1, v1] | vertex_array[16]=[size, size, -size] |
| texCoord[17]=[u0, v1] | vertex_array[17]=[-size, size, -size] |
| 后『UV紋理』 | 『xyz頂㸃』 |
| texCoord[18]=[u0, v0] | vertex_array[18]=[size, -size, size] |
| texCoord[19]=[u1, v0] | vertex_array[19]=[-size, -size, size] |
| texCoord[20]=[u1, v1] | vertex_array[20]=[-size, size, size] |
| texCoord[21]=[u0, v0] | vertex_array[21]=[size, -size, size] |
| texCoord[22]=[u1, v1] | vertex_array[22]=[-size, size, size] |
| texCoord[23]=[u0, v1] | vertex_array[23]=[size, size, size] |
| 右『UV紋理』 | 『xyz頂㸃』 |
| texCoord[24]=[u1, v0] | vertex_array[24]=[size, -size, size] |
| texCoord[25]=[u1, v1] | vertex_array[25]=[size, size, size] |
| texCoord[26]=[u0, v1] | vertex_array[26]=[size, size, -size] |
| texCoord[27]=[u1, v0] | vertex_array[27]=[size, -size, size] |
| texCoord[28]=[u0, v1] | vertex_array[28]=[size, size, -size] |
| texCoord[29]=[u0, v0] | vertex_array[29]=[size, -size, -size] |
| 左『UV紋理』 | 『xyz頂㸃』 |
| texCoord[30]=[u1, v0] | vertex_array[30]=[-size, -size, -size] |
| texCoord[31]=[u1, v1] | vertex_array[31]=[-size, size, -size] |
| texCoord[32]=[u0, v1] | vertex_array[32]=[-size, size, size] |
| texCoord[33]=[u1, v0] | vertex_array[33]=[-size, -size, -size] |
| texCoord[34]=[u0, v1] | vertex_array[34]=[-size, size, size] |
| texCoord[35]=[u0, v0] | vertex_array[35]=[-size, -size, size] |

本文Java係指Java 虛擬機(JVM), 下載最新版本Java Runtime Environment’ (JRE).
| 下載 Java8 |
| Windows 適用64 位 Java |
移除舊版 Java
| JavaUninstallTool.exe |
| 解除安裝 Java 版本 |



手多多落單買Kingston 32GB號称『讀』每秒200MB. 支持『USB3.2』要剪爛包裝拎U盤出蒞.用 CrystalDiskMark測『讀』每秒達196MB.
| DTKN/32GB | 『讀』Read MB/s | 『寫』Write MB/s |
| Seq Q32 T1 | 196.7 | 26.3 |
默認FAT32, 上世紀WIN98己用FAT32檔案系統, 單壹文檔受4BYTE尋址影响极限4GB, 所以自WinNT用NTFS檔案系統, 高清4K電影可超過4GB. 需NTFS或exFAT支持, 『exFAT』優勢係『Windows』同『MAC』皆支持.
| 檔案系統 | 操作系統 |
| FAT32 | Window9X |
| NTFS | WindowNT |
| exFAT | WindowNT同MAC |



前兩年買『SEAGATE 8TB EXOS™ ST8000NM0055』畀影片逼爆. 又唔舍得刪. 本蒞諗住砌台NAS. 估價成萬蚊. 冇米諗唔掂.
睇啱『SEAGATE 16TB Exos™ X16 ST16000NM001G』.16TB畀8TB大壹倍. 应刻可撑多两年先砌NAS.
係Windows10磁碟分區. PMR垂直式-氦氣密封設計.CrystalDiskMark測寫230MB讀230MB
| 型號 | X16 ST16000NM001G |
| 接口類型 | SATA3 6Gb/S |
| 容量 | 16TB |
| 轉速 | 7200RPM |
| 緩存 | 256MB |
| 工作負荷評級 | TB/年 |
| 平均故障間隔時間 | 250萬小時 |
| 寫 | 231.9MB/S |
| 讀 | 231.7MB/S |




『Kensington指紋鎖』識認差又貴又唔好,係网買雜牌『指紋鎖』, 智能学習每次登入补缺指紋. 其触摸面比『Kensington』大. 即使手指有水亦可識認指紋.
需装ELANTECH触摸板驱动. 稳新版舊版識認唔到, 下載『.cab』并解壓.
| 指紋鎖驅動 |
| ELAN Finger Print – Biometric – 3.10.11001.10606 |
| https://www.catalog.update.microsoft.com/Search.aspx?q=elan+fingerprint |
可能要手動装
設置『Windows Hello指紋』



近蒞Win10頻頻死幾, 收屘仲話稳唔到『QT5webenginecore.dll』, 次次入Win10彈出蒞,
| RadeonSoftware.exe-系統錯誤 |
| 程式碼執行冇法繼續, 事因稳唔到『QT5webenginecore.dll』重装程式或可修正. |
睇蒞係『ATI-Radeon RX550 Series』驅動損壞, 去AMD网下載. 重新装. 可能係Win10 -Update覆盖ATI驅動導至頻頻死幾.
| amd-software-adrenalin-edition-22.4.1-win10-win11-april5.exe |

唔知幾時Windows10『搜尋』辰咗,填唔到字.睇蒞又係更新造成. 微軟己畀出修復方案, 修正注册表.
| 撳『WIN+R』執行『CMD』 |
| reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Search /v BingSearchEnabled /t REG_DWORD /d 0 /f |
| reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Search /v CortanaConsent /t REG_DWORD /d 0 /f |

書法家『青柳衡山』揮毫. 登録漢字最多草書字庫. 約萬餘字,公開免費,商業領域冇制限使用.有『TrueType』『OpenType』版. 將『KouzanBrushFontSousyo.ttf』『KouzanSoushoOTF.otf』字庫複製係『C:\Windows\Fonts』
| 衡山毛筆フォント草書 (揮毫/青柳衡山) |
| https://opentype.jp/kouzansousho.htm |

『經倫羅盤』需『漢字庫』, 書法家『青柳衡山』揮亳書寫. 登録萬三漢字.公開免費,商業領域冇制限使用.有『TrueType』『OpenType』版. 將『KouzanMouhituFont.ttf』『KouzanMouhituFontOTF.otf』字庫复制係『C:\Windows\Fonts』
| 衡山毛筆フォント |
| https://opentype.jp/kouzanmouhitufont.htm |
| C:\Windows\Fonts |
| 毛筆體 |
朋友發信息畀我,話台電腦冇法上網.Firefox顯示『Proxy 伺服器拒絕連線』.拋開網絡硬體網線問題. 更大可能軟體設定錯誤. Win10有hosts檔案用于記錄『Domain Name』輿『 IP』對應影射.冇需透過DNS伺服器獲取.以本文方式開啟hosts檔案.『127.0.0.1 localhost』將所有『Domain Name』影射到本機.刪此行後保存hosts即可.而『127.0.0.1 localhost』多為『自由門』退出時遺留.重啟『自由門』後再退出可自行刪除.
| 檔案 | 位置 |
| hosts | C:\Windows\System32\drivers\etc |
| Firefox | Proxy 伺服器拒絕連線 |
| IE | Proxy 伺服器沒有回應 |
| Edge | 無法連線到 Proxy 伺服器 |
| Firefox | Proxy 伺服器拒絕連線
Firefox 無法與您設定的 Proxy 伺服器連線。 請檢查 Proxy 設定是否正確。 與您的網路管理員聯絡,確定 Proxy 伺服器正常運作。 |
| IE | Proxy 伺服器沒有回應
檢查您的 Proxy 設定 127.0.0.1:8580。 請確定您的防火牆設定不會封鎖您的網頁存取。 要求您的系統管理員提供協助。 |
| Edge | 無法連線到 Proxy 伺服器
試試看 確定您的防火牆設定不會封鎖您的網頁存取 要求您的系統管理員提供協助 |
今日用Visual Studio寫段暴力碰撞運算破解數學問題.用sprintf()將結果輸出命令行.掟C4996錯,語法明明冇錯.源於C4996,警告此類C函式,無安全檢測可能會記憶體越界讀寫.其實問題根本無甘嚴重.最好方法禁用此類錯誤檢測.
| #pragma warning(disable:4996) |
| error C4996: ‘sprintf’: This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. |
是時候啓動『風水羅盤』工程.本安裝Visual Studio 2017但睇到有2019版與時并進.到微軟官網下載Microsoft Visual Studio 2019並安裝.
| 語言 | 『C++』 |
| 平臺 | 『Windows』 |
| 類型 | 『空白專案』
『使用適用於Windows的C++從頭開始,不會提供任何起此檔案』 |
| 專案名稱 | 『工程代號』 |
| 位置 | 專案位置即『檔案夾』 |
| 解決方案名稱 | 與『專案名稱』一致 |
| 將解決方案與專案置於相同目錄中 | 若工程簡單則勾選激活.
激活:『方案』文檔位於專案『位置』 禁用:『方案』文檔位於『解決方案名稱』 |
| 一般/字元集 | 使用Unicode字元集 |
| 連接器/系統/子系統 | 圖形界面『Windows(/SUBSYSTEM:WINDOWS)』
命令行界面『主控台(/SUBSYSTEM:CONSOLE)』 |
| 副檔名『.c』 | C編譯器 |
| 副檔名『.cpp』 | C++編譯器 |
| VS安裝檔案資料夾 | C:\Program Files (x86)\Microsoft Visual Studio\ |
| VS應用程式 | C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\devenv.exe |
近日條千兆内網時不時自動斷線.只好改用WIFI連線.密碼明明正確卻鏈接出錯.細想之下可能是加密類型搞錯.
| 網路名稱 | SSID即『WIFI名』 |
| 安全性類型 | 『不驗證(開放)』
『WEP』 『WPA2-Personal』 『WPA2-Enterprise』 『802.1x』 |
| 加密類型 | 『無』
『WEP』 『AES』 |
| 安全性金錀 | 密碼 |
| 隱藏字元 | 以密文填入密碼. |
| 自動啓動這個連線 | WIFI自動連線 |
| 即使網路未廣播,還是進行連線
警告:若選取此選項,你電腦的隱私權可能會有風險. |
| 網路名稱 | WIFI名 |
| 安全類型 | 密碼 |
| 自動連線 | 開機自動連線WIFI |
| 即使此網路未廣播,還是進行連線 |
之前幫朋友台Lenovo.預裝Win10 Home版,台機裝得太多垃圾.想重新裝Win10 Pro OEM版.居然無法裝Pro版.本應挂載Win10 U盤時可選Pro或Home版.台機跳過此步.而裝後自動激活為Home版.通過『變更産品金鑰』亦無法升級爲Pro版.
| 設定->啓用->變更產品金鑰 |
細想之下可能Lenovo在BIOS寫入Home 版KEY ID.每裝Win10都自動安裝Home版.按照網上介紹在檔案夾『sources』加入『ei.cfg』.同樣未能安裝Pro版.最後只能退回『專業版』PRO加錢買『企業版』FRE解決.
Windows10_FRE_64Bit_HK
Windows10 企業版 64Bit漢化版
之前買Windows10 RRO 64BIT 漢化版在台聯想電腦裝來裝去都是Home版.只好加錢賣Windows 10 Enterprise 64Bit OEM.OEM簡包只有DVD與KEY號.順利激活但冇自帶IE.連『iexplore.exe』都冇.
| C:\Program Files\internet explorer\iexplore.exe |
朋友需重裝Win10,因他開公司有大量往來郵件資料.需買卓面外置『磁碟機』備份.睇來睇去仲是SEAGATE信得過.『希捷』睿品3.5寸.本想買10TB需2018紋.而8TB只1230紋包郵. 用Crystal Disk Mark實測『寫』193.5MB/S『讀』151.6MB/S.以磁碟機速度算超班馬.
因3.5寸磁碟較耗電需外接叉機.有多種插頭畀旅行用,但考慮其重量並非適宜旅行携帶,更好方法是買台NAS電腦.實測唔支持WinXP系統.且非USB3.1可能USB3.0已滿足其傳送要求.
| 品牌 | 希捷SEAGATE |
| 產品 | SEAGATE Backup Plus Hub |
| 型號 | STEL8000300 |
| 磁碟 | 3.5寸 |
| 容量 | 8TB |
| 電腦 | Win7或以上 |
因朋友部電腦想重新安裝Win10.但Win10為MAK版即一次性激活.便在網絡幫其購買OEM版Windows10可多次安裝.本想購買企業版但只有Pro版有香港漢文版. DVD版230紋包郵比起零售版廉價幾倍.所謂OEM指『代工生產』微軟以低廉價格大批量售賣給電腦廠家.至於爲何唔買USB版仍因U盤易壞,之前購買Kingston-U盤多已損壞.
因當今電腦已無標配DVD-ROM.更好方法製作USB版安裝Win10.
製作ISO映像
燒錄ISO映像
近日師兄台Windows10啓動後連不上網.部電腦岩岩入厰重裝Windows10翻來.睇來是因Application Store自更新整壞.可按下列三部嘗試解決.
| 重置市集緩存 |
| 1. 按『Win+R』鍵, 鍵入『CMD』啓動『命令提示字元』 |
| 2. 重置市集緩存鍵入『WSReset.exe』 |
| 調整 Internet 選項 |
| 1. 啓動IE『C:\Program Files\internet explorer\iexplore.exe』 |
| 2. 工具->網際網路選項->進階 |
| 3. 勾選『SSL 3.0』『TLS 1.0』『TLS 1.1』『TLS 1.2』按『套用』 |
| 解除Microsoft Store後重裝 |
| 1. 『以系統管理員身份執行』開啓Windows Powershell |
| 2. 解除市集鍵入『get-appxpackage *store* | remove-Appxpackage』 |
| 3. 重裝市集鍵入『add-appxpackage -register “C:\Program Files\WindowsApps\*Store*\AppxManifest.xml” -disabledevelopmentmode』 |

在Windows10安裝『要塞3』啓動時缺失『d3dx9_43.dll』. 彈出『系統錯誤』視窗如下:
| 系統錯誤 |
| 程式碼執行無法繼續,因爲找不到d3dx9_43.dll 重新安裝程式或許可以修正此問題. |
在網上單獨下載『d3dx9_43.dll』將其放置在遊戲檔案下. 其地圖編輯器『MapEditor.exe』可正常啓動.但遊戲可開啓但黑屏.『d3dx9_43.dll』其實是Driect3D模塊.即DirectX Runtime無完整安裝.
進如遊戲若自動退出.可通過設置『相容模式』解決.

近日發現有些電影有像無音.提示如下
| 無法播放該影訊.
DirectX驅動程式未正確安裝或音效裝置被停用. 在渲染下列Pin時失敗了 Built-in AVI<->AC3/DTS::XForm Out |
其實這類播放器均用DirectPlay解碼.下載PotPlayer codec安裝解碼器:
| 解碼元件 | 文檔 |
| Core Files | FFmpegMininum64.dll |
| OpenCodec Files | OpenCodecUnity64.dll |
| FFmpeg Files | FFmpeg64.dll |
| Inter H.264 MVC Decoder | Libmfxsw64.dll |

重裝Windows10後發現羅技滑鼠可移動.但『開此菜單』有焦點.但左右鍵均無法『點選』『點擊』.而桌面可以『點擊』 細想之下Windows10圖形介面用3D特效.因為滑鼠即插即用,可能無正確安裝滑鼠驅動造成.果然安裝羅技驅動即『 點擊』問題
| 滑鼠 | 驅動 |
| 微軟 | Microsoft IntelliPoint 8.2 Mouse Software for Windows – 64 bit |
| 羅技 | Logitech Options |


Windows10支持手寫輸入漢字.但經過好幾次改版.與Android全屏手寫輸入相比. 依然相差很遠.而且要較長時閒適應
Windows10大量操作需要『管理員權限』.下面總結出已知方法.
| 啓用Administrator權限 | 效期 |
| Ctrl + Shift + Enter | 單次 |
| 滑鼠右擊『以系統管理員權限身分執行』 | 單次 |
| 內容->相容性->以系統管理員的身分執行此程式 | 永久 |
| 直接以Administrator管理員登入Windows10 | 永久 |

Administrator使用者默認被『停用』.你要手動啓用它,才能以Administrator登入







微軟自1993年推出WinNT到現在.都基於當年WinNT架構.發展到當今Win10已非常成熟.與Win9x架構相比系統崩潰機率已大幅減小.Windows安裝也越來越容易.因只120GB磁碟裝Windows10略欠不足.剛好淘汰只固態混合型500GB磁碟.用於做Windows10系統盤剛合適.


若用U盤重裝Win10.你需要進入底板BIOS設定USB啟動


當Win9x盛行年代系統經常崩潰.安裝Windows從最早磁盤引導加載光驅.記得有同學因無法加載光驅驅動,而將Win95分多張1.44磁盤安裝.後期光驅直接引導安裝Windows.到現在USB啟動安裝已很方便.下面以製作Win10安裝U盤為例


近日在Windows10-64Bit安裝早年『PS7、PhotoshopCS、PhotoshopCS2』等.但安裝程式『Setup.exe』一直在後臺等待居然無法轉到前臺,它等屬Win32程式Win10理應支持.可以肯定有某個程式佔用系統造成阻塞
而PhotoshopCS2安裝後無法啟動則可通過『相容模式』解決.


當想對『磁碟』測速.而手邊又無安裝CrystalDiskMark.可借助Windows10內置測速工具:
D是盤符.但對希捷酷鷹2TB監控盤測量,結果可能有問題.讀取速度達7802.15MB/S
| 命令 | 簡介 |
| winsat disk -drive d | 執行下列所有讀寫測試 |
| winsat disk -drive d -ran -read | 磁盤隨機讀取16 MB時間
Disk Random 16.0 Read |
| winsat disk -drive d -seq -read | 磁盤順序讀取64 MB時間
Disk Sequential 64.0 Read |
| winsat disk -drive d -seq -write | 磁盤順序寫取64 MB時間
Disk Sequential 64.0 Write |
| winsat disk -drive d -flush -seq | 循序寫入的平均讀取時間 |
| winsat disk -drive d -flush -ran | 隨機寫入的平均讀取時間 |


『磁碟』製造商自上世紀未達到萬轉.但一直未有普及.而現役『磁碟』多為5400轉、5900轉、7200轉.可見轉速提高讀寫加快,但工藝與壽命都難以保障.
HD Tune Pro提供『自動噪聲管理』AAM(Automatic Acoustic Management),其原理降低『磁盤』轉速而減小震動和噪聲.從而延長使用壽命.因直接更改『磁碟』固件,所以一次更改永遠有效






近日使用CrystalDiskInfo檢測希捷固態混合磁碟.『磁碟健康狀態』出現黃色警告.而『重定位磁區計數』以達100即已出現壞道.此『磁碟』只用一年多D.睇來只能更換『磁碟』.因為要儘量保障數據安全.聽講HGST『磁碟』故障率最低但價格稍高.而希捷酷鷹為監控而設計.可以長時間大量讀寫數據而不出故障.而且價格比HGST稍低.
網上落單盒裝全新行貨.安裝後分區並格式.使用CrystalDiskMark測『讀寫』速度均接近150MB/S,『機械磁碟』達如此高速,實超我預期.
| 性能 | 簡介 |
| 品牌 | SEAGATE希捷 |
| 系列 | SKYHAWK酷鷹 |
| 型號 | ST200VX008 |
| 接口 | SATA3 SATA 6GBS |
| 轉速 | 5900轉 |
| 容量 | 2TB |
| 級別 | 64路7*24全天監控級 |
| 讀取READ | 149.4MB/S |
| 寫入WRITE | 148.6MB/S |


S.M.A.R.T即『自監測分析與報告技術』據我記憶所及應在上世紀未出現.當時並不清其用途.近日使用CrystalDiskInfo檢測磁碟健康狀態.其工作原理就是讀取磁碟S.M.A.R.T.資訊.磁碟工作其間會自動監測電機、電路、磁盤、磁頭狀態進行分析與記錄.此技術支持『HDD,SSD, SSHD,USB,RAID,NVME』磁碟.在檢測『希捷固態混合磁碟』出現黃色警號.『重定位磁區計數』以達100遠超臨界值36.亦即壞道出現.雖然使用HD Tune Pro進行『錯誤掃描』未見壞區,這只是由於壞道被映射到後備扇區.屬于『磁碟』自我修復.當『磁碟』發現壞區時,便將其物理空間指向到特定無損區域進行重映射修復,從而使硬盤出現壞區仍可使用.但當過多壞道出現.後備扇區消耗殆盡而無法再重映射時,就會出現壞區並不可修復.若繼續使用必造成數據損失.此『磁碟』只使用一年多D睇來質量確實有問題.
| 警訊 | 簡介 |
| 綠色 | 安全使用 |
| 黃色 | 危險警告,更換磁碟轉移數據 |
| 紅色 | 死亡邊緣,備份數據暫停使用 |
| ID | 屬性名稱 | 簡介 |
| 01 | 底層資料讀取錯誤率 | 磁頭讀取數據時錯誤率.只有SSD此值為0 |
| 03 | 碟片啟動時間 | |
| 04 | 馬達啟動關閉次數 | |
| 05 | 重定位磁區計數 | 出現壞區.若數值不斷整長說面壞道擴散 |
| 07 | 尋道錯誤率 | |
| 09 | 總通電時間 | 用於確定是否返修盤 |
| 0A | 啟動重試次數 | 電機重啟量.有可能是USB電壓不足 |
| 0C | 開關電源次數 | |
| B8 | 終端校驗出錯 | |
| BB | 報告不可糾正錯誤 | |
| BC | 通訊超時 | 磁碟無法連接.若非零則可能是電源或獲數據線問題 |
| BD | 磁頭寫入高度 | |
| BE | 氣流溫度 | |
| BF | 加速度錯誤率 | |
| C0 | 電源關閉磁頭收回計數 | |
| C1 | 載入/卸載迴圈計數 | |
| C2 | 硬碟溫度 | |
| C5 | 等候重定的磁區計數 | 假性壞區可修復 |
| C6 | 無法校正的磁區計數 | 不修復壞區量 |
| C7 | UltraDMA高速傳輸模式錯誤次數 |

CrystalDiskMark用於測量各種存儲『HDD、SSD、USB』磁碟速度基準軟件.它由日本開發商Hiyohiyo開發而且是免費軟件.我手頭上只有幾款磁碟.讀寫速度差距非常之大.基本上都以SSD>HDD>USB這樣排列.從下表可睇到『固態混合型』HDD+SSD讀取快寫入慢.而最慢則是USB移動磁碟.
| 磁碟 | 類型 | 讀MB/S | 寫MB/S |
| THNSNH128GBST : 128.0 GB | SSD | 548.1 | 502.7 |
| ST2000VX008-2E3164 : 2000.3 GB | HDD | 149.4 | 148.6 |
| ST500LX025-1U717D : 500.1GB | SSHD | 171.3 | 57.67 |
| ST1000LM024 HN-M101MBB : 1000.2 GB | HDD+USB3.0 | 39.10 | 36.28 |
| 測試 | 簡介 |
| ALL | 執行所有測試 |
| Seq Q32T1 | 順序讀寫測試32隊列,1線程測試 |
| 4KiB Q8T8 | 4KiB分頁隨機讀寫測試8『佇列』,1『執行緒』 |
| 4KiB Q32T1 | 4KiB分頁隨機讀寫測試32『佇列』,1『執行緒』 |
| 4KiB Q1T1 | 4KiB分頁隨機讀寫測試1『佇列』,1『執行緒』 |


若你購買全新磁碟非返修盤,必定是未建立分區.當你連結電源與SATA還需要建立分區.在Windows10有兩種方法分別是『儲存空間』與『磁碟管理』
使用『儲存空間』建立分區並格式化
使用『磁碟管理』建立分區並格式化

你明明沒有在C盤安裝很多『軟件』或『遊戲』.卻Windows10經常報『磁盤空間不足』首先刪除所有『臨時文檔』和『禁用休眠』
若依然如事.可以嘗試查找大於128M

近日發現Photoshop經常報『暫存磁盤』不足.睇來C盤空間不足.一睇『設定->系統->本機C:->系統與保留->休眠檔案』佔用25.5GB. 『休眠』只是將記憶體保存在磁盤,開機時從磁盤載入以提高開機速度.其實Windows10開機速度還是要睇硬件驅動.現只要禁用『休眠』即可釋放大量磁盤空間以解燃眉之急.
重啟休眠系統『powercfg –h on』
休眠檔案壓縮50%『 powercfg –h size 50』
是時候將之前所學OpenGL/DirectX知識粘合成一完整遊戲.最簡單是『第一人稱視角射擊遊戲』FPS(First-person Shooter). 通過控制『準星』描准『怪物』按滑鼠左鍵發射『飛彈』.若擊中便會『爆炸』並擊殺『怪物』,其實它會在另地在生.若擊中地面則會『爆炸』.按鍵盤上下鍵在山地中前後移動.若近距離接近『怪物』它會另轉面自動走開(AI部分). 所有『怪物』與『飛彈』都是MD2模型.按ESC鍵退出遊戲.下載FPS:
下面所需要文章與代碼:

DirectX本是用於取替OpenGL給遊戲廠商使用.但遊戲廠商集體反抗.才另microsoft支持OpenGL.而且自DirectX6全面使用COM模型開發.DirectX是設計用於『影片』『聲音』『輸入』『網絡』抽象軟件界面結口.DirectX接口由microsoft定義.而底層則有驅動程式與硬件進行通信.開發者完全無需理會硬件之間差異.如果硬件不支持則由DirectX進行模擬.
#include “..\DirectX\Include\ddraw.h”
#include “..\DirectX\Include\dinput.h”
#include “..\DirectX\Include\dsound.h”
#ifdef _WIN64
#pragma comment(lib, “DirectX\Lib\x64\ddraw.LIB”)
#pragma comment(lib, “DirectX\Lib\x64\dinput8.LIB”)
#pragma comment(lib, “DirectX\Lib\x64\dxguid.LIB”)
#pragma comment(lib, “DirectX\Lib\x64\dsound.LIB”)
#else
#pragma comment(lib, “DirectX\Lib\x86\ddraw.LIB”)
#pragma comment(lib, “DirectX\Lib\x86\dinput8.LIB”)
#pragma comment(lib, “DirectX\Lib\x86\dxguid.LIB”)
#pragma comment(lib, “DirectX\Lib\x86\dsound.LIB”)
#endif
上面方法是指定工程目錄.令外你還可制定Visual Studio搜索目錄:
在DirectX8之前分別使用DirectSound和DirectMusic處理音頻播放. DirectSound用于處理聲波回放和捕足,而DirectMusic則是加載和播放所有聲音主要組件.但在DirectX8之後合平DirectXAudio組件.若你需要播放MIDI睇『DirectMusic之播放MIDI』

WAV音頻格式由Electronic Arts(電子協會)創建.它基於.IFF(Interchange File Format)對等交換文件格式.允許不同音檔格式通過鑲套技術進行編碼.
上兩編文章『DirectSound』與『DirectSound3D』均從WAV音檔中讀音頻數據.WAV音檔好再於結構簡單無需解壓. 我建議先把所有WAV音檔數據格式統一. 改為『單聲道Mono』(因為你只有一個咪頭)、採樣頻率11025Hz、採樣精度8bit.後再由遊戲引擎載入.
.WAV數據由以下三部份組成:
| 數據 | 簡序 |
| RIFF | .IFF標記 |
| FORMAT | 音頻格式 |
| DATA | 音頻數據 |
| RIFF數據 | 所占空間(BYTE) | 簡序 |
| chunkID | 4 | 塊ID,必須為’RIFF’ |
| chunkSize | 4 | 塊長度(不包含chunkID[4]和chunkSize所占空間) |
| FORMAT數據 | 所占空間(BYTE) | 簡序 |
| waveID | 4 | WAVE ID,必須為’WAVE’ |
| chunkID | 4 | 塊ID,必須為’fmt ‘ |
| chunkSize | 4 | 塊長度(不包含chunkID[4]和chunkSize所占空間) |
| wFormatTag | 2 | 壓縮(格式)標誌默認WAVE_FORMAT_PCM脈衝編碼格式 |
| wChannels | 2 | 聲道:『單聲道Mono』或『雙聲道Stereo』 |
| dwSamplesPerSec | 4 | 採樣頻率(11025Hz,22050Hz,44100Hz) |
| dwAvgBytesPerSec | 4 | 每秒播放字節數(SamplesPerSec * BlockAlign) |
| wBlockAlign | 2 | 字節對齊,單聲道8bit占1byte.雙聲道16bit占4yte. |
| wBitsPerSample | 2 | 每個採樣點位精度.有8bit、16bit、24bit、32bit |
| information | 2 | 附加信息(未必有此數據) |
| 數據塊 | 所占空間(BYTE) | 簡序 |
| chunkID | 4 | 塊ID,必須為’data’ |
| chunkSize | 4 | 音頻數據長度 |
| Data | chunkSize | 音頻數據 |
讀取WAV數據.wav指向文檔數據.size為文檔長度
bool Load_WAV(SOUND3D_PTR sound3D, PBYTE wav, int size){
1.數格塊
RIFF_PTR riff;
WAVE_FORMAT_PTR format;
WAVE_DATA_PTR data;
2.讀取RIFF數據
riff = (RIFF_PTR)wav;
3.判斷是否RIFF
if (riff->id != WAVE_RIFF_ID)
return false; // 返回出錯!
4.讀取WAVE_FORMAT_CHUNK
format = (WAVE_FORMAT_PTR)((PBYTE)wav + sizeof(RIFF));
if (format->waveID != WAVE_ID ||
format->chunkID != WAVE_FMT_ID ||
format->wFormatTag != WAVE_FORMAT_PCM)
return(false); // 返回出錯!
5.讀取數據塊
data = (WAVE_DATA_PTR)((PBYTE)wav + sizeof(RIFF) + (int)format->chunkSize + sizeof(WAVE_CHUNK));
if (data->chunkID != WAVE_DATA_ID)
return(false); // 返回出錯!
6.獲取音頻數據
PBYTE audio = (PBYTE)malloc(data->chunkSize);
memcpy(audio, &data->data, data->chunkSize);
return true;
}

經多日努力終於可以在3D空間中添加中添加3D效果,所帶來極強真實感效果有時比3D渲染更好.而且x86和x64均正確運行.在演示程式中.『狼嚎』放置於山地中心.隨著按方向鍵移動相機聲音產生變化.單這點很多書本例程均不正確. 3D狼嚎程式:下載
而DirectSound如何模擬3D效果.3D即有xyz三軸笛卡爾座標,以此定義聲源和聽者位置、速度、方向.要注意Z軸是指向屏幕內部.所以3D效果需單聲道.
typdef struct{
IDirectSoundBuffer * buffer; // 輔助緩存
IDirectSound3DBuffer8 * buffer3D;// 3D緩存
float x,y,z;// 音源3D位置
PBYTE data;// 音頻數據
int size;// 所占空間
}SOUND3D;
SOUND3D sound3D;
而一般我地有左右兩個音箱,最多四角四個音箱.要模擬3D感知效果要素如下:
『WAV數據載入』後交與DirectSound代碼如下:
1.創建聲卡接口,NULL為與默認聲卡鏈接
IDirectSound8 * direct_sound3D = NULL;// 默認聲卡接口
DirectSoundCreate8(NULL,&direct_sound3D,NULL);
2.設置為優先等級,允許設定主緩存音頻數據格式並獲取IDirectSound3DListener8接口
direct_sound3D->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);// 優先級別
3.初始化Directsound主緩存,主緩存代表聲卡,並設置格式
DSBUFFERDESC buffer;// 緩存格式描述
ZeroMemory(&buffer, sizeof(DSBUFFERDESC));// 清零
buffer.dwSize = sizeof(DSBUFFERDESC);// 所占空間
buffer.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;//3D緩存並使用聲卡緩存
4.創建默認聲卡緩存接口
IDirectSoundBuffer * DirectSound3D_Buffer = NULL;
direct_sound3D->CreateSoundBuffer(&buffer, &DirectSound3D_Buffer, NULL);
5.獲取3D空間『聽者』
IDirectSound3DListener8 * DirectSound3D_Listener;// 3D聽者
DirectSound3D_Buffer->QueryInterface(IID_IDirectSound3DListener, (VOID**)&DirectSound3D_Listener);
6.設置緩存數據格式
WAVEFORMATEX format;//緩存格式描敘
memset(&format, 0, sizeof(WAVEFORMATEX));
format.cbSize = 0;//總是0.
format.wFormatTag = WAVE_FORMAT_PCM; //脈衝編碼格式
format.nChannels = 1; //(聲道數目)1為單聲道回放
format.nSamplesPerSec = 11025;//(每秒的樣本)總是這個速度
format.wBitsPerSample = 8;//聲音為8Bit
format.nBlockAlign = 1;//字節對齊,單聲道8bit占1byte.雙聲道16bit占4yte.
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; //每秒播放字節數
DirectSound3D_Buffer->SetFormat(&format); //設置主緩存音頻格式
7.現在建立輔助聲音緩存
DSBUFFERDESC desc;// 緩存格式描敘
memset(&desc,0,sizeof(DSBUFFERDESC));
desc.dwSize = sizeof(DSBUFFERDESC);//dsbd的大小
desc.dwFlags = DSBCAPS_CTRL3D |// 請求3D BUFFER
DSBCAPS_CTRLVOLUME | // 緩存擁有音量控制功能
DSBCAPS_CTRLFREQUENCY | // 緩存擁有頻率控制功能
DSBCAPS_GLOBALFOCUS |
DSBCAPS_CTRLPOSITIONNOTIFY | // 3D位置
DSBCAPS_GETCURRENTPOSITION2; // 播放位置
desc.dwBufferBytes = sound3D->size;//聲音數據的大小.
desc.guid3DAlgorithm = DS3DALG_DEFAULT;// 主緩沖區在 DSBCAPS_CTRL3D 模式下可以啟用這個選項
desc.lpwfxFormat = &format;// 緩存數據格式
8.創建輔助聲音緩衝器
direct_sound3D->CreateSoundBuffer(&desc, &sound3D->buffer, NULL);
9.獲取3D空間緩存
sound3D->buffer->QueryInterface(IID_IDirectSound3DBuffer, (VOID**)&sound3D->buffer3D);
10.把數據寫入聲音輔助緩存,輔助(二級)聲音緩存是自循環
UCHAR audio_ptr_1 = NULL,audio_ptr_2 = NULL; //指向緩存第一與第二部分
DWORD audio_len_1 = 0, audio_len_2 = 0; //第一與第二緩存長度
11.鎖住空間
sound3D->buffer->Lock(0,//寫入指針指向位置
sound3D->size,//要鎖定空間大小.
(void **)&audio_ptr_1,//第一個部分開始地址.
&audio_len_1,//第一個部分長度
(void **)&audio_ptr_2,//第二個部分開始地址.
&audio_len_2,//第二個部分長度
DSBLOCK_FROMWRITECURS );
11.複製數據到聲音緩沖存儲器,拷貝到圓形緩沖存儲器的第一段中
memcpy(audio_ptr_1, sound3D->data, audio_len_1);
12.拷貝到圓形緩沖存儲器的第二段中
memcpy(audio_ptr_2, (sound3D->data + audio_len_1), audio_len_2);
13.解鎖
sound3D->buffer->Unlock(audio_ptr_1, audio_len_1,audio_ptr_2, audio_len_2);
14.設置音源3D位置與距離
DS3DBUFFER param;
memset(¶m, 0, sizeof(DS3DBUFFER));
param.dwSize = sizeof(DS3DBUFFER);
sound3D->buffer3D->GetAllParameters(¶m);
param.flMaxDistance = sound3D->max;// 聲音最大距離 DS3D_DEFAULTMAXDISTANCE
param.flMinDistance = sound3D->min;// 聲音最小距離 DS3D_DEFAULTMINDISTANCE
param.vPosition.x = x; //音源3D位置
param.vPosition.y = y;
param.vPosition.z = -z;// Z軸反轉
param.dwMode = DS3DMODE_NORMAL;// 默認,使用3D座標設定音源位置和
sound3D->buffer3D->SetAllParameters(¶m, DS3D_IMMEDIATE);// 立即設定
15.正確設置音源因子與3D聽者位置,關鍵部分是不要設置DS3DMODE_HEADRELATIVE(頭部模式)
DS3DLISTENER param;
memset(¶m, 0, sizeof(DS3DLISTENER));
param.dwSize = sizeof(DS3DLISTENER);
DirectSound3D_Listener->GetAllParameters(¶m);
param.flDopplerFactor = 0; //多譜勒頻移,一般設為0
param.flRolloffFactor = 0.1f; // 衰減率,此直越大衰減越快.一般設為0.1f~0.5f
param.vPosition.x = x; //聽者3D位置
param.vPosition.y = y;
param.vPosition.z = -z;
DirectSound3D_Listener->SetAllParameters(¶m, DS3D_IMMEDIATE);
16.循環播放音頻數據
sound3D->buffer->Play(0,0,DSBPLAY_LOOPING);
17.單次播放
sound3D->buffer->Play(0, 0, 0);
18.停止音頻播放
sound3D->buffer->Stop();
19.釋放DirectSound3D
sound3D->buffer3D->Release();// 釋放3D緩存
sound3D->buffer->Release();// 釋放輔助緩存
DirectSound3D_Buffer->Release(); // 釋放聲卡主緩存
direct_sound3D->Release();// 釋放聲卡

DirectMusic主要用於播放midi數據,而且你無需寫分析器.DirectMusic自動完成所有操作,本.演示程式按ALT鍵彈出MENU再Open打開midi音檔.按+/-鍵控制音量.本想編譯X64版本卻出現『REGDB_E_CLASSNOTREG Class not registered.』所以只有x86程式下載:
DirectMusic是建基於DirectSound,不過DirectMusic會在Init()中自啟動它.DirectMusic是Dirext中第一個完全COM化組件,所以DirectMusic無需LIB庫.只需以下幾個頭文檔.
#include “..\DirectX\Include\dmplugin.h”
#include “..\DirectX\Include\dmksctrl.h”
#include “..\DirectX\Include\dmusici.h”
#include “..\DirectX\Include\dmusicc.h”
#include “..\DirectX\Include\dmusicf.h”
但安裝最新DXSDK安裝包(DX11),以上幾文件頭文件據然穩唔倒.我只可在舊版SDK拷貝過來工程文檔下.如果你把文檔拷貝到工程檔案下還需要小小修改#include <dmplugin.h>改為#include “dmplugin.h”
而編譯時DirectMusic有大量GUID無法鏈接.出現LNK2001下錯誤.
“錯誤 LNK2001 無法解析的外部符號 _CLSID_DirectMusicPerformance”
古計是從”dxguid.lib”刪除左.無需執著這些小問題.只要自已加上即可.你需要初此化GUID宏指令
#define INIT_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) const GUID name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
並把下面GUID複製到全域變量
INIT_GUID(CLSID_DirectMusicPerformance, 0xd2ac2881, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicSegment, 0xd2ac2882, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicSegmentState,0xd2ac2883, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicGraph, 0xd2ac2884, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicStyle, 0xd2ac288a, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicChordMap, 0xd2ac288f, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicComposer, 0xd2ac2890, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicLoader, 0xd2ac2892, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(CLSID_DirectMusicBand, 0x79ba9e00, 0xb6ee, 0x11d1, 0x86, 0xbe, 0x0, 0xc0, 0x4f, 0xbf, 0x8f, 0xef);
INIT_GUID(GUID_Download, 0xd2ac28a7,0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(GUID_Unload, 0xd2ac28a8, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(GUID_StandardMIDIFile, 0x6621075, 0xe92e, 0x11d1, 0xa8, 0xc5, 0x0, 0xc0, 0x4f, 0xa3, 0x72, 0x6e);
INIT_GUID(GUID_DirectMusicAllTypes, 0xd2ac2893, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(GUID_PerfMasterVolume, 0xd2ac28b1, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicLoader, 0x2ffaaca2, 0x5dca, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
INIT_GUID(IID_IDirectMusicGetLoader, 0x68a04844, 0xd13d, 0x11d1, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6);
INIT_GUID(IID_IDirectMusicObject, 0xd2ac28b5, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicSegment, 0xf96029a2, 0x4282, 0x11d2, 0x87, 0x17, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicSegmentState, 0xa3afdcc7, 0xd3ee, 0x11d1, 0xbc, 0x8d, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
INIT_GUID(IID_IDirectMusicPerformance, 0x7d43d03, 0x6523, 0x11d2, 0x87, 0x1d, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicGraph, 0x2befc277, 0x5497, 0x11d2, 0xbc, 0xcb, 0x0, 0xa0, 0xc9, 0x22, 0xe6, 0xeb);
INIT_GUID(IID_IDirectMusicStyle, 0xd2ac28bd, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicChordMap, 0xd2ac28be, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicComposer, 0xd2ac28bf, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicBand, 0xd2ac28c0, 0xb39b, 0x11d1, 0x87, 0x4, 0x0, 0x60, 0x8, 0x93, 0xb1, 0xbd);
INIT_GUID(IID_IDirectMusicLoader8, 0x19e7c08c, 0xa44, 0x4e6a, 0xa1, 0x16, 0x59, 0x5a, 0x7c, 0xd5, 0xde, 0x8c);
INIT_GUID(IID_IDirectMusicPerformance8, 0x679c4137, 0xc62e, 0x4147, 0xb2, 0xb4, 0x9d, 0x56, 0x9a, 0xcb, 0x25, 0x4c);
INIT_GUID(IID_IDirectMusicSegment8, 0xc6784488, 0x41a3, 0x418f, 0xaa, 0x15, 0xb3, 0x50, 0x93, 0xba, 0x42, 0xd4);
INIT_GUID(IID_IDirectMusicSegmentState8, 0xa50e4730, 0xae4, 0x48a7, 0x98, 0x39, 0xbc, 0x4, 0xbf, 0xe0, 0x77, 0x72);
INIT_GUID(IID_IDirectMusicStyle8, 0xfd24ad8a, 0xa260, 0x453d, 0xbf, 0x50, 0x6f, 0x93, 0x84, 0xf7, 0x9, 0x85);
| 接口對像 | 簡介 |
| IDirectMusic | 你無需自已創建DirectMusic,因為她會自動創建 |
| IDirectMusicPerformance | 對MIDI播放進行控制,構建該對象時同時創建IDirectMusic |
| IDirectMusicLoader | 用於加載音頻文檔,如MIDI.這樣你以擁有MIDI的載入器 |
| IDirectMusicSegment | Segment代表音樂數據塊 |
| IDirectMusicSegmentState | 數據塊狀態 |
| IDirectMusicProt | MIDI音樂輸出硬件設備.微軟合成器 |
| IDirectMusic | 擁有一個DSP(Digital Signal Processing)MIDI數字實時轉換器 |
下面是IDirectMusic播放MIDI代碼簡介:
1.首先你必須初此化COM
CoInitialize(NULL);
2.創建DirectMusicPerformance接口
IDirectMusicPerformance *DirectMusic_Performance = NULL;
CoCreateInstance(CLSID_DirectMusicPerformance,NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance,(LPVOID*)&DirectMusic_Performance);
3.初此化 DirectMusicPerformance設置為audiopath,自動構建IDirectMusic和IDirectSound接口
DirectMusic_Performance->Init(NULL, NULL, hWnd);
4.增加數字輸出播放端口,使用微軟合成器作為默認設備
DirectMusic_Performance->AddPort(NULL);
5.創建MIDI載入器
IDirectMusicLoader * DirectMusic_Loader = NULL;
CoCreateInstance(CLSID_DirectMusicLoader,NULL,CLSCTX_INPROC, IID_IDirectMusicLoader8,(LPVOID*)&DirectMusic_Loader);
6.你需要在初此化時設定音量
long volume = DMUS_VOLUME_MAX;
DirectMusic_Performance->SetGlobalParam(GUID_PerfMasterVolume, &volume, sizeof(long));
7.載入midi音檔. DirectMusic非常聰面.你只需給出『路徑』和『文檔名』即可完成MIDI載入
DMUS_OBJECTDESC objdesc;
memset(&objdesc, 0, sizeof(DMUS_OBJECTDESC));// 清零
objdesc.dwSize = sizeof(DMUS_OBJECTDESC);
objdesc.guidClass = CLSID_DirectMusicSegment;
objdesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
8.Utf8轉換為UNICODE寬字符
MultiByteToWideChar(CP_UTF8, NULL, filename, (int)strlen(filename), objdesc.wszFileName, DMUS_MAX_FILENAME);//文檔名
MultiByteToWideChar(CP_UTF8, NULL, category, (int)strlen(category), objdesc.wszCategory, DMUS_MAX_CATEGORY);//路徑
9.設置當前搜索目錄
hResult = DirectMusic_Loader->SetSearchDirectory(GUID_DirectMusicAllTypes, objdesc.wszCategory, false);
10.如果MIDI音檔編譯進資源文檔(resource)或者自已讀取MIDI音檔數據
objdesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_MEMORY;
objdesc.pbMemData = data;//指向midi數據
objdesc.llMemLength = size;// 數據長度
11.獲取IDirectMusicSegment音色庫接口,並自動載入midi數據
IDirectMusicSegment * segment;
DirectMusic_Loader->GetObject(&objdesc,IID_IDirectMusicSegment,(void**)&segment);
12.指定音色庫segment
segment->SetParam(GUID_StandardMIDIFile,-1,0,0,DirectMusic_Performance);
13.將音色庫segment載入到IDirectMusicPerformance
segment->SetParam(GUID_Download, -1, 0, 0, DirectMusic_Performance);
14.設置循環播放
segment->SetRepeats(DMUS_SEG_REPEAT_INFINITE);
15.單次循環播放
midi->segment->SetRepeats(0);
16.終於可以播放MIDI音檔
IDirectMusicSegmentState * segstate;
DirectMusic_Performance->PlaySegment(segment,0,0, &segstate);
17.停止MIDI播放
DirectMusic_Performance->Stop(segment, NULL, 0, 0);
18.禦載DLS樂器段
segment->SetParam(GUID_Unload, -1, 0, 0, (void*)DirectMusic_Performance);
19.釋放指定MIDI音樂段.
segment->Release();
20.停止播放所有的MIDI音樂段
DirectMusic_Performance->Stop(NULL,NULL, 0, 0);
21.關閉IDirectMusicPerformance對像.
DirectMusic_Performance->CloseDown();
22.釋放IDirectMusicPerformance對像.
DirectMusic_Performance->Release();
23.釋放載入器.
DirectMusic_Loader->Release();

DirectSound顧明思義可以讓你控制聲卡播放聲音和音樂. DirectSound由許多模塊和接口組成,編譯時需要庫文檔DSOUND.LIB和頭文檔DSOUND.H
WAV音檔播放演示程式,按+/-鍵控制聲音音量.按Open載入WAV音檔:下載
1.啟動DirectSound
IDirectSound接口:DirectSound的主COM對象.它代表聲卡硬件.若你裝有多個聲卡,則每個DirectSound對象代表一個聲卡.創建主聲卡對象,輸入NULL與默認聲卡鏈接
LPDIRECTSOUND direct_sound;
DirectSoundCreate(NULL,&direct_sound,NULL);
if (direct_sound == NULL)
return false;
2.設置默認協作等級
設定遊戲控制聲卡的等級.一般設定為DSSCL_NORMAL即可.當程式具有焦點時,即可播放聲音.但並不妨礙其它程式. DirectSound自動創建22kHz,立體聲,8bit主緩存(默認).hWnd為當前窗口句柄
direct_sound->SetCooperativeLevel(hWnd,DSSCL_NORMAL);
| 參數 | 簡介 |
| DSSCL_NORMAL | 默認等級 |
| DSSCL_PRIORITY | 優先等級.允許設定主緩存數據格式 |
| DSSCL_EXCLUSIVE | 當窗口在前臺時擁有優先等級 |
| DSSCL_WRITEPRIMARY | 完全控制主緩存 |
3.輔助(二級)音頻緩存
『輔助緩存』即代表你想播放的音頻.但聲卡上SRAM卻容量有限,而且我印象中只在ISA版CREATIVE(創新)聲卡有出現.『輔助緩存』分為『靜態緩存』與『動態緩存』.『靜態緩存』用於存儲經常播放短聲音.『動態緩存』用於存儲較長聲音.DirectSound不斷播放不斷把音頻數據寫入『輔助緩存』.使用稱為Circular Buffering(環形緩存)結構,一個指針寫入音頻數據,另一個指針讀取音頻數據.創建輔助聲音緩衝器
HRESULT IDirectSound::CreateSoundBuffer(
LPCDSBUFFERDESC lpcDSBufferDesc,
LPLPDIRECTSOUNDBUFFER lplpDirectSoundBuffer,
IUnknown FAR* pUnkOuter
);
4.設置緩存格式描敘,單聲道11kHz,8bit
AVEFORMATEX format;
format.cbSize = 0;//高級,總是0.
format.wFormatTag = WAVE_FORMAT_PCM;//PCM編碼
format.nChannels = 1;//(聲道數目)1為單聲道播放
format.nSamplesPerSec = 11025;// 樣本速度11kHz
//設置字節對齊.
//單聲道乘以1字節(8Bit), 它將是1字節字節對齊.
//立體聲它將是雙聲道8Bit, 它將是2字節字節對齊.
//如果它是立體聲系統和16Bit它將是4字節對齊.
format.nBlockAlign = 1;
format.wBitsPerSample = 8;//聲言位數為8BIT
format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;// 每秒字節
3.設定聲音緩沖存儲器描敘表
DSBUFFERDESC buffer;// 描述結構
memset(&buffer,0,sizeof(DSBUFFERDESC));// 清零
buffer.dwSize = sizeof(DSBUFFERDESC);// 結構所占空間
//設置DirectSoundBuffer的描述結構的標誌
buffer.dwFlags = DSBCAPS_CTRLPAN | // 緩存擁有總控制功能
DSBCAPS_CTRLVOLUME | // 緩存擁有音量控制功能
DSBCAPS_CTRLFREQUENCY; // 緩存擁有頻率控制功能
buffer.dwBufferBytes = sound_size;//聲音數據大小.
buffer.lpwfxFormat = &format;//”WAV文件格式描述結構”
4.創建輔助(二級)音頻緩存
LPDIRECTSOUNDBUFFER sound_buffer;
direct_sound->CreateSoundBuffer(&buffer, &sound_buffer, NULL);
if (sound_buffer == NULL)
return false;
5.鎖住緩存
UCHAR *audio_ptr_1 = NULL, //指向緩存第一部分
UCHAR *audio_ptr_2 = NULL; //指向緩存第二部分
DWORD audio_len_1 = 0, //第一緩存長度
DWORD audio_len_2 = 0; //第二緩存長度
sound_buffer->Lock(0,//寫入指針指向位置
sound_size,//要鎖定大小,音頻數據長度.
(void **)&audio_ptr_1,//第一個部分開始地址.
&audio_len_1,//第一個部分長度
(void **)&audio_ptr_2,//第二個部分開始地址.
&audio_len_2,//第二個部分長度
DSBLOCK_FROMWRITECURSOR);// 緩存當前寫入點將被鎖住.
6.拷貝到環形緩存第一部分, sound_size為音頻數據
memcpy(audio_ptr_1, sound_data, audio_len_1);
7.拷貝到環形緩存第二段中
memcpy(audio_ptr_2, (sound_data + audio_len_1), audio_len_2);
8.解鎖
sound_buffer->Unlock(audio_ptr_1,audio_len_1,audio_ptr_2,audio_len_2);
9.循環播放聲音
sound_buffer->Play(0,0,DSBPLAY_LOOPING);
10.若單次播放聲音
sound_buffer->Play(0, 0, 0);
11.當退出遊戲時需要釋放緩存和聲卡
sound_buffer->Release();
direct_sound->Release();

在windows你可以通過WM_MOUSEMOVE被動(消息驅動)接受滑鼠當前位置.但若在遊戲中若想得到滑鼠『偏移量』和『按扭』(是否按下)DirectInput則可以幫助你你重新獲得滑鼠每次『偏移量』和『按扭』信息(主動讀取).然後讓你可以重新繪畫新『指標』. 而無需Windows自帶『指標』.若你有多個滑鼠.則所有『偏移量』合併到單一設備中.
滑鼠移動演示程式:下載
演示代碼.在Init()中調用
1.調用DirectInputCreate()生成IDirectInput接口
IDirectInput * direct_input;
DirectInputCreate(GetModuleHandle(NULL),DIRECTINPUT_VERSION, &direct_input,NULL);
2.獲取滑鼠GUID_SysMouse為全域主滑鼠設備ID碼
direct_input->CreateDevice(GUID_SysMouse, &direct_mouse, NULL);
3.設置滑鼠協作等級(前臺) 非獨占訪問,訪問滑鼠時不會干涉其它應用程序訪問該滑鼠.當應用程序在前臺和後臺時都能時用該滑鼠.
direct_mouse->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
4.設置數據格式. c_dfDIMouse為DirectInput通用滑鼠全域常量
direct_mouse->SetDataFormat(&c_dfDIMouse);
5.從DirectInput獲取滑鼠
direct_mouse->Acquire();
6.載入滑鼠紋理,並且背景透明
mouse->texture.IsAlpha = true;
Load_File_Texture(&mouse->texture, hInstance, filename);
7.綁定紋理
Bind_Image_Texture(&mouse->texture,GL_REPEAT, GL_REPEAT,GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,GL_REPLACE);
8.滑鼠尺寸
mouse_size = 20;
9.現在你可以從滑鼠中獲取輸入.在你Update()更新中獲取滑鼠狀態.若你失去設備鍵盤,需要重新從DirectInput獲取鍵盤.
DIMOUSESTATE state;
while (direct_mouse->GetDeviceState(sizeof(DIMOUSESTATE), &state) == DIERR_INPUTLOST)//
{ // 已失去設備,重新從DirectInput獲取鍵盤
if (direct_mouse->Acquire()==S_OK)
return false;
}
10.定義鼠標結構
typedef struct DIMOUSE_TYP{
int x, y;// 滑鼠座標
int screen_width, screen_height;// 窗口寬和高
float size;// 鼠標尺寸
bool button_left, button_right, button_middle; // 滑鼠按鈕,若true則為按下
TEXTURE texture;// 指標紋理
}DIMOUSE, *DIMOUSE_PTR;
DIMOUSE mouse;
11.重新計算滑鼠位置
mouse->x = mouse->x + state.lX;
mouse->y = mouse->y + state.lY;
12.判斷是否超出窗口邊界
if (mouse->x < 0)
mouse->x = 0;
if (mouse->x >= screen_width)
mouse->x = screen_width-1;
if (mouse->y < 0)
mouse->y = 0;
if (mouse->y >= screen_height)
mouse->y = screen_height – 1;
13.提取滑鼠按鈕
mouse->button_left = state.rgbButtons[0] & 0x80; //滑鼠左鍵
mouse->button_right = state.rgbButtons[1] & 0x80; // 滑鼠右鍵
mouse->button_middle = state.rgbButtons[2] & 0x80;// 滑鼠中鍵
14.當你退出遊戲時.需要釋放滑鼠和DirectInput對像
direct_mouse->Release();
direct_input->Release();

DirectInput是DirectX COM組件之一. 它讓你無需理會『鍵盤』硬件驅動程式. DirectInput為輸入設備提供統一接口,當然輸入設備需已安裝硬件驅動.而且你需要安裝『DirectX SDK』並設定include和LIB搜索路徑,或者加入工程項目中.若你想讀取鍵盤狀態.用法與GetAsyncKeyState()使用基本相似.但它的KEY鍵並非是ASCII碼.若你有多個鍵盤.則所有的輸入合併到單一設備中.
演示程式按鍵盤在屏幕中顯示對應字母:下載
演示代碼.在Init()中調用當然你需檢測返回值HRESULT
1.調用DirectInputCreate()生成IDirectInput接口
IDirectInput * direct_input;
DirectInputCreate(GetModuleHandle(NULL),DIRECTINPUT_VERSION, &direct_input,NULL);
2.獲取鍵盤, GUID_SysKeyboard為全域主鍵盤設備ID碼
IDirectInputDevice * direct_keyboard;
direct_input->CreateDevice(GUID_SysKeyboard, &direct_keyboard, NULL);
3.設置鍵盤協作等級, 非獨占訪問,訪問該設備時不會干涉其它應用程序訪問該設備. 並且當應用程序在前臺和後臺時都能時用該設備.
direct_keyboard->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE |DISCL_BACKGROUND);
4.設置數據格式. c_dfDIKeyboard為DirectInput通用鍵盤全域常量
direct_keyboard->SetDataFormat(&c_dfDIKeyboard);
5.從DirectInput獲取鍵盤.
direct_keyboard->Acquire();
6.你現在以可以從鍵盤中獲取輸入.在你Update()更新中獲取鍵盤狀態.若你失去設備鍵盤,需要重新從DirectInput獲取鍵盤
while(direct_keyboard->GetDeviceState(sizeof(UCHAR) * 256, direct_keystate)== DIERR_INPUTLOST)
{
if(direct_keyboard->Acquire() != S_OK)
return false;
}
7.當你退出遊戲時.需要釋放鍵盤和DirectInput對像
direct_keyboard->Release();
direct_input->Release();

FPS全稱為Frames Per Second.用於統計遊戲與影片每秒的渲染畫面(幀)次數.此值越高畫面越流暢,電影以每秒24格菲林進行播放.所以你的遊戲要流暢無停頓感.需要不低於24幀最好高於30幀.當然幀數越高越好.
FPS算法如下:
FPS = 100 * Frequency / (currentTime – startTime);
Frequency為時鐘頻率. currentTime與 startTime為前後兩次時鐘
Windows下你需要高精度計數器:
返回硬件級高精度時鐘頻率,若返回0代表系統不支持.
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
返回硬件級高精度計數器,若返回0代表系統不支持.
BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);
LARGE_INTEGER:為64BIT結構
此兩個函式需要winbase.h頭文檔和Kernel32.LIB庫
#include <winbase.h>
#pragma comment(lib, “Kernel32.LIB”)
定義如下FPS結構:
typedef struct FPS_TYP {
LARGE_INTEGER Frequency;// 計數器的頻率
LARGE_INTEGER startTime;// 啟動時鐘
float Frames;// 每秒渲染幀數
int n;// 臨時幀計數器
}FPS,*FPS_PTR;
初此化高精度定時器
bool Init_FPS(FPS_PTR fps)
{
// 返回硬件支持的高精度計數器的頻率
if (QueryPerformanceFrequency(&fps->Frequency) == false)
return false;
// 獲取啟動時鐘
QueryPerformanceCounter(&fps->startTime);//
return true;
}
計算每秒渲染幀數,每100幀進行一次計算
float Get_FPS(FPS_PTR fps)
{
++fps->n;
if (fps->n > 100)
{
LARGE_INTEGER currentTime;
// 返回高精度計數器
QueryPerformanceCounter(¤tTime);
fps->Frames = (float)100 * (float)fps->Frequency.QuadPart / ((float)currentTime.QuadPart – (float)fps->startTime.QuadPart);
fps->startTime = currentTime;// 重置時間
fps->n = 0;
}
return fps->Frames;
}
计算两次测量所花费时间
float Get_Counter_FPS(FPS_PTR fps){
LARGE_INTEGER currentTime;//当前时钟
// 返回高精度计数器
QueryPerformanceCounter(¤tTime);
float seconds = ((float)currentTime.QuadPart – (float)fps->startTime.QuadPart) / (float)fps->Frequency.QuadPart;
fps->startTime = currentTime;
return seconds;
}

互聯網公司Cloudflare推出免費的DNS服務,與APNIC進行合作使用它的IP位址(1.1.1.1), Cloudflare保證你使用它的DNS服務會絕對保證你的隱私,絕不會出售您的數據,或用來定位廣告,更不會記錄您的 IP 位址.
而且Cloudflare聲稱它的DNS服務比其它公司的DNS服務速度更快,比起GOOGLE的快最小兩倍.
| DNS | 響應速度 |
| 1.1.1.1 | 14.8ms |
| Cisco OpenDNS | 20.6ms |
| Google Public DNS | 34.7ms |
| Average ISP | 68.23ms |
在Windows10設定DNS伺服器IP位址

近日Windows10更新版本1709時總會彈出錯誤碼0xc1900205,使用『Windows Update』與『Windows10更新小幫手』均出錯並彈出下面的信息:
| Microsoft 無法在您的電腦上安裝重要的安全性更新。
請連絡 Microsoft 支援服務以獲得解決此錯誤的協助。 請將此錯誤碼提供給支援人員: 0xc1900205 |
通過如下方法即可修復:
| net stop wuauserv
Dism.exe /online /Cleanup-Image /StartComponentCleanup Dism.exe /online /Cleanup-Image /RestoreHealth net start wuauserv |
3.我已生成cmd文檔可以直接下載:

在Windows10下很多命令需要『系統管理員』Administrator的『權限』才能執行,有4中方法打開

Windows其中一個最好用的工具是『Microsoft屏幕放大鏡』,通過win鍵與+鍵啟動.如果你有『Microsoft鼠標』可以通過安裝『IntelliPoint8.2』激活母指鍵啟動『Microsoft屏幕放大鏡』.安裝後要重啟電腦. 通過『檔案總管\控制台\所有控制台項目\滑鼠』設定『母指鍵』.在『全屏幕』下按『母指鍵』+『鼠標滑輪』用於梯相最好用.
| 快捷鍵 | 簡介 |
| Win鍵與+鍵 | 方大/啟動放大鏡 |
| Win鍵與-鍵 | 縮小 |
| Win鍵與ESC鍵 | 關閉放大鏡 |
| 鼠標前母指鍵 | 啟動放大鏡/關閉放大鏡 |
| 鼠標前母指鍵+鼠標滑輪 | 方大/縮小(這個最好用) |
| CTRL+ALT+F | 全屏幕 |
| CTRL+ALT+L | 透鏡 |
| CTRL+ALT+D | 以連接擴充座(分屏) |
| CTRL+ALT+SPACE | 預覽全屏幕 |
| CTRL+ALT+I | 反色 |

近日將WinXP升為Win10,將VC6升為VS2016.按Menu後在WindowProc()會接收到兩個重複的WM_COMMAND Message.而Accelerator更會接收多個WM_COMMAND Message.同樣的代碼在WinXP和VC6重未出現.不斷查看Winmain()事件循環.因為遊戲引擎是實時驅動而非消息驅動的.所以使用PeekMessage ()而非GetMessage()讀取消Message.當改為while(GetMessage (&msg, NULL, 0, 0))消息驅動後問題無在出現.梯來是MSG這個Message沒有被清空道至.調用memset(&msg, 0, sizeof(MSG)); 問題得到完美解決.
主事件循環代碼簡介
1.WINDOWS消息的存儲器
MSG msg;
2.Accelerator加速鍵表的句柄
HACCEL hAccel;
hAccel =::LoadAccelerators(main_instance,”ACCEL”);
2.主事件循環非消息驅動的
while(true) {
3.清空MSG
memset(&msg, 0, sizeof(MSG));
4.從事件對列中獲得消息
PeekMessage(&msg,NULL,0,0,PM_REMOVE);
5.由 PostQuitMessage(0) 發送的WM_QUIT消息,被PeekMessage()檢測到跳出主循環
if(msg.message == WM_QUIT)
break;
6.處理加速鍵表
if(!::TranslateAccelerator(main_window,hAccel,&msg)) {
7.處理和轉換加速鍵.
TranslateMessage(&msg);
3.調用WinProc對消息進行處理,從MSG結構取的參數並傳遞.
DispatchMessage(&msg);
}
}

之前一值無法使用ALT鍵,因查找唔到其VK_ALT對應的『VIRTUAL CODE』,近日把WinXP切底拋棄改用Win10,發現很多程式均使用ALT鍵展示或隱藏MENU. 細想VK_ALT即等於VK_MENU,下面是使用ALT鍵展示與隱藏MENU源代碼
1.在resource.h加入
#define IDALT 1000
2.在resource.rc加入加速表,一定要加入ALT否則MENU會獲得焦點要按量下ALT鍵,另不要用VK_LMENU和VK_RMENU
ACCEL ACCELERATORS
BEGIN
VK_MENU, IDALT, VIRTKEY, ALT, NOINVERT
END
3.在main()修改消息循環
MSG msg;//消息 msg是WINDOWS放置下一個消息的存儲器,
HACCEL hAccel; // 加速鍵表的句柄
hAccel =::LoadAccelerators(main_instance,”ACCEL”); // 加速鍵表的句柄
while(GetMessage(&msg,NULL,0,0)) //從事件對列中獲得消息
{ //由 PostQuitMessage(0) 發送的WM_QUIT消息,被PeekMessage()檢測到
if(msg.message == WM_QUIT)
break;// 跳出主循環
if(!::TranslateAccelerator(main_window,hAccel,&msg))// 處理加速鍵表
{
TranslateMessage(&msg);//處理和轉換加速鍵.
DispatchMessage(&msg);//調用WinProc對消息進行處理,從MSG結構取的參數並傳遞.
}
}
4.在WinProc加入
if(msg == WM_COMMAND)
{ // 處理菜單命令
if (LOWORD(wParam) == IDALT)
{ main_menu = ::LoadMenuA(NULL,”MAIN_MENU”);// 主菜單
if (::GetMenu(main_window) == NULL)
::SetMenu(main_window, main_menu);// 設定菜單
else
::SetMenu(main_window, NULL);// 設定菜單
}
}


近日終於遠離最愛的VC6安裝VC2017,新增專案時居然無發現C/C++的選項,暈難道C已被拋棄?經一番鑽然才悟個中方法

『Windows10 Update Assistant』又稱為『Windows 10 更新小幫手』會自動彈出下載並安裝更新.但更新後卻把我的『港版Win10』變為『台版Win10』更新時還不能保留原有程式.最煩的是經常自動彈出.即使卸載Uninstall後還是會自動安裝. 經一番研究只禁『Windows10 Update Assistant』自動彈出,而『Windows10 Update』仍在後臺自動更新系統

Windows Defender是Windows10內置免費的既時保護查找惡意程式,但它卻經常錯報誤報影響日常工作,而且暫用大量資源,需然可然暫時關閉既時保護.『設定/更新與安全性/Windows Defender/既時保護/關閉』但更新病毒資料庫後又會開啟,你需要停止系統服務


記憶體(RAM)容量對計算機性能起直接的影響,而另一個關鍵參數記憶體(RAM)帶寬(Bandwidth) ,帶寬越高與CPU之間交換數據更快,更有利提高計算機性能.
計算公式如下:
帶寬(Bandwidth)=工作頻率(DRAM Frequency)*位寬(DataWidth)
| 公式 | 簡介 | |
| 工作頻率Frequency | 工作頻率=記憶體頻率*通道數量 | 相當於車速 |
| 位寬(DataWidth) | SDRAM、DDR和DDR2、DDR3、DDR4的總線位寬均為64位 | 相當於路寬 |
可以通過命令行模式輸入『wmic memorychip』查看記憶體(RAM)的所有參數如上圖
| ConfiguredClockSpeed | DataWidth | Voltage | Speed | TypeDetail |
| 時鐘速度 | 位寬 | 電壓 | 工作頻率 | 記憶體容量 |
以DDR4-2400為例:
工作頻率:2400 MHz
位寬:64Bit=8Byte
例計算DDR4-2400記憶體(RAM)帶寬
2400MHz*64bit/8=19200 Mbyte/s=PC19200
例計算DDR400記憶體(RAM)帶寬
400MHz*64bit/8=3200Mbyte/s=PC3200

Windows程式就是單獨的.exe執行文件.但若程式需要讀取文檔才能運行.可以將其與.exe文件一起放置,但這樣就失去保密性.更好處理方法是將文檔編譯進.exe執行文件.這樣執行程式就無需附帶其它文檔.以VC為例:
把資源文檔編譯進.exe執行文件
| 定義資源文檔 | 簡介 |
| resources.rc
Heightmap RAW “res\\heightmap.raw” |
通過字符串名定義
RAW為類型名 Heightmap為資源名 |
| resource.h
#define ID_MAP 1500 resources.rc ID_MAP RAW “res\\heightmap.raw” |
通過整數標識符定義
ID_MAP為資源ID 也可直接使用數字 |
讀取資源文檔示例
C代碼版本
hInstance:程式的實例句柄
filename:資源文檔名
type:類型名
PBYTE Read_RES(HINSTANCE hInstance,char *filename,char * type)
{// 查找資源
HRSRC hRsrc =::FindResource((HMODULE)hInstance,filename,type);
if(hRsrc == NULL)
return false;
//加載資源
HMODULE hGlobal = (HMODULE)::LoadResource((HMODULE)hInstance,hRsrc);
// 獲取文檔的字節長度
int size =::SizeofResource((HMODULE)hInstance,hRsrc);
// 鎖定資源並獲取指針
PBYTE res = (PBYTE) ::LockResource(hGlobal);
// 分配內存空間
PBYTE data = (PBYTE)malloc(size);
// 拷貝數據
memcpy(data,res,size);
if(hGlobal)
FreeResource(hGlobal); // 釋放資源句柄
return data;
}

Windows菜單可以通過實現單選(點選)與多選(勾選)展現當前狀態.你無需更改MENU結構,只需運行時更改菜單項MENUITEM的標記.
| 菜單多選與單選(函式示例) | 簡介 |
| HMENU menu = GetSubMenu(main_menu,1); | 獲取子菜單句柄 |
| CheckMenuRadioItem(
menu, ID_FIRST, ID_LAST, ID_CHECK, MF_BYCOMMAND); |
單項選擇
ID_FIRST第一個菜單 ID_LAST最後一個菜單ID ID_CHECK單選(點選)菜單ID
|
| CheckMenuItem(menu,
ID_CHECK, MF_BYCOMMAND|MF_CHECKED); |
選擇多個菜單項(多項選擇) |
| CheckMenuItem(menu,
ID_CHECK, MF_BYCOMMAND|MF_UNCHECKED); |
取消選擇菜單項(多項選擇) |

此程式用於查閱鍵消息的虛擬代碼(Virtual Code)與按鍵狀態(Key state)如上圖:下載程式
在Windows訪問鍵盤有五種方法
| Windows鍵盤消息 | 觸發條件 |
| WM_CHAR | 按下鍵盤 |
| WM_KEYDOWN | 按下鍵盤 |
| WM_KEYUP | 鬆開鍵盤 |
| GetAsyncKeyState() | 任何時候都可讀取鍵盤 |
| Windows鍵盤消息 | wParam | lParam |
| WM_CHAR | ASCII碼(ASCII Code) | 按鍵狀態Key state |
| WM_KEYDOWN | 虛擬代碼(Virtual Code) | |
| WM_KEYUP |
| 按鍵狀態Key state(BIT) | 變量 | 簡介 |
| 0~15 | 整數 | 按鍵重複次數(repeat count) |
| 16~12 | 整數 | 掃描碼(scan code) |
| 24 | bool | 擴展鍵標識,若為1為該鍵為擴展鍵,如右側的ALT鍵和CTRL鍵 |
| 25~28 | 無使用 | |
| 29 | bool | 若為1則ALT鍵被按下,否則為0 |
| 30 | bool | 前一個鍵的狀態 |
| 31 | bool | 若為1鍵被釋放,若為0鍵被按住. |

近日要實現文件拖放,如果只實現接收則較為簡單,下麵把實現原理記下.
int Query_DragAndDrop(HDROP hdrop,PROC_DRAGANDDROP Proc_DragAndDrop)
{
int File_Num;
TCHAR File_Path[2056];
int File_Index;
File_Num = ::DragQueryFile(hdrop,-1,NULL,0);// 獲取文件個數
for(File_Index = 0; File_Index < File_Num; ++File_Index)
{ // 獲取拖放文件
::DragQueryFile(hdrop,File_Index,File_Path,sizeof(File_Path));
Proc_DragAndDrop(File_Path);// 處理文件
}
::DragFinish(hdrop);// 釋放空間
return 1;
}

按扭BUTTON可以設定圖標,但有幾點需要需注意:

對話框圖標在模板中不能設置,需要
1. 準備一張512×512圖片
2. 使用IconWorkshop轉換成ICO圖標
3. 分辯率勾選48×48,32×32,24×24,16×16,位數32Bit(RGBA),16Bit,8Bit(256色)即可.
4. 在你VC工程目標下創建ICON文件夾,把ICO圖標複製於此.
5. 在RSOURCE.RC文件加上,要注意第一條記錄也是應用圖標
IDR_MAINFRAME ICON “ICO\\logo.ico”
6. 在對話框WM_INITDIALOG設置
HICON hIcon = LoadIcon(main_instance,_T(“IDR_MAINFRAME”));//載入圖標
::SendMessage(hWnd, WM_SETICON, true, (LPARAM)hIcon);//設置大圖標
::SendMessage(hWnd, WM_SETICON, false, (LPARAM)hIcon);//設置小圖標

如果程式需要讀取大量數據可使用SQLite3關係數據庫,但如果只是讀寫小量文本數據,則使用文本一行行地保存文本更方便,擴展名最好改為.db下麵給設計思路.
讀取文本數據
寫入文本數據
讀取文本的C代碼
bool Read_DB()
{
FILE * stream=NULL; // 文件流句柄
char text[2056];
stream = _wfopen(L”text.dat”,L”r+t”);// 以文本方式打開文件
if(stream == NULL)
return false;// 無法打開文件
// 讀取一行
while(fgets(text,sizeof(text),stream) != NULL)
{ //去除字符串中最後面 “換行符” “空格”
TrimRight(text);
// 處理文本
// ……….
}
fclose(stream); // 關閉文件句柄
return true;
}
追加一行文本的C代碼
bool Save_DB(char * text)
{
FILE * stream=NULL; // 文件流句柄
// 以文本方式打開文件
stream = _wfopen(L”text.dat”,L”a+t”);
if(stream == NULL)
return false;// 無法打開文件
::fputs(text,stream);// 寫入數據
::fputs(“\n”,stream);// 換行
fclose(stream);// 關閉文件句柄
return true;
}

對話框(DIALOG)模板可以設定顯示位置,但因屏幕大小不一,總想讓對話框在屏幕居中顯示.
下面給出C源代碼便於移值到其它工程
bool CentreWindow(HWND hWnd)
{
RECT rect;
int width,height;
int x,y;
if(IsWindow(hWnd) == false)
return false;
::GetWindowRect(hWnd,&rect); // 獲取窗口的
width = rect.right – rect.left; // 計算窗口寬度
height = rect.bottom – rect.top; // 計算窗口高度
x = GetSystemMetrics(SM_CXSCREEN)/2-width/2;// 計算窗口居中X
y = GetSystemMetrics(SM_CYSCREEN)/2-height/2;// 計算窗口居中Y
SetWindowPos(hWnd,HWND_TOP,x,y,0,0,SWP_NOSIZE); // 移動窗口
return true;
}

啟動瀏覽器最簡單的方法是使用ShellExecute(),但無返回進程句炳,要關閉瀏覽器只能查找窗口.更好的方法是CreateProcess()啟動瀏覽器新進程並打帶網頁,並返回進程句柄,方便關閉瀏覽器.
BOOL CreateProcess(LPCTSTR lpApplicationName,//執行模塊名填空NULL即可
LPTSTR lpCommandLine,//命令行填”瀏覽器Path+空格+網頁URL”
LPSECURITY_ATTRIBUTES lpProcessAttributes,//進程屬性 LPSECURITY_ATTRIBUTES lpThreadAttributes,//線程屬性
BOOL bInheritHandles, //繼承進程句柄false
DWORD dwCreationFlags, //創建標誌填CREATE_NEW_CONSOLE
LPVOID lpEnvironment, //進程環境
LPCTSTR lpCurrentDirectory,// 進程的工作路徑填NULL
LPSTARTUPINFO lpStartupInfo, //STARTUPINFO結構
LPPROCESS_INFORMATION lpProcessInformation//PROCESS_INFORMATION結構
);
下麵給打開網頁源代碼,便於
bool Open_Url(char * url,char * browser_Path)
{
int result = 0;
char CommandA[2056];
WCHAR CommandW[2056];
int length;
SECURITY_ATTRIBUTES Security_Attributes_Process;// 進程屬性
SECURITY_ATTRIBUTES Security_Attributes_Thread;// 線程屬性
STARTUPINFO Startup_Info;// 啟動信息
PROCESS_INFORMATION Process_Information;// 進程信息
strcpy(CommandA,browser_Path);
strcat(CommandA,” “);
strcat(CommandA,url);
// 轉換UNICODE
length = MultiByteToWideChar(CP_ACP, NULL, CommandA, strlen(CommandA), CommandW, sizeof(CommandW));
CommandW[length] = NULL;
// 進程屬性
Security_Attributes_Process.nLength = sizeof(SECURITY_ATTRIBUTES);
Security_Attributes_Process.lpSecurityDescriptor = NULL;
Security_Attributes_Process.bInheritHandle = true;
// 線程屬性
Security_Attributes_Thread.nLength = sizeof(SECURITY_ATTRIBUTES);
Security_Attributes_Thread.lpSecurityDescriptor = NULL;
Security_Attributes_Thread.bInheritHandle = true;
// 啟動信息
ZeroMemory( &Startup_Info, sizeof(STARTUPINFO) );
Startup_Info.cb = sizeof(STARTUPINFO);
ZeroMemory( &Process_Information, sizeof(PROCESS_INFORMATION) );
// 創建進程
result = CreateProcessW(NULL,
CommandW,
&Security_Attributes_Process,
&Security_Attributes_Thread,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&Startup_Info,
&Process_Information);
// 獲取進程句柄
if(result != 0)
return true;
else
return false;
}

Windows默認瀏覽器的路徑在註冊表(REGEDIT.EXE)的HKEY_CLASSES_ROOT\http\shell\open\command\,提取數據需要使用下面三個註冊表操作函數.並給出設計思路源碼
char Browser_Path[2056];// 瀏覽器路徑
// ————————————————————–
// 獲取系統默認瀏覽器路徑
// ————————————————————–
char * Get_WebBrowserPath_SEO(void)
{
long ret;
HKEY hKey;// 註冊表句柄
WCHAR path[2056];//
char data[2056];
DWORD length;
// 打開註冊表
// HKEY_CLASSES_ROOT\http\shell\open\command
ret = RegOpenKeyExW(HKEY_CLASSES_ROOT,L”http\\shell\\open\\command”,0,KEY_ALL_ACCESS,&hKey);
if(ret != ERROR_SUCCESS)
return NULL;
// 獲取REG_SZ
DWORD type = REG_SZ;//類型
length = sizeof(path);//
ret = RegQueryValueExW(hKey,NULL,NULL,&type,(PBYTE)path,&length);
if(ret != ERROR_SUCCESS)
return NULL;
// 關閉註冊表句柄
RegCloseKey(hKey);
// 轉換為UTF-8
length = WideCharToMultiByte(CP_UTF8, NULL, path, wcslen(path), data, sizeof(data), NULL, NULL);
data[length] = NULL;
// 清零
memset(Browser_Path,0,sizeof(Browser_Path));
// 提取路徑
for(int i = 0,index = 0;i<(int)length; ++i)
{
if(data[i] == ‘”‘ && index != 0)
break;// 讀取完畢跳出
if(data[i] != ‘”‘)
{
Browser_Path[index] = data[i];
++index;
}
}
return Browser_Path;// 返回路徑
}

因為Windows控件全部使用UNICODE編碼字符(或ANSI),而我文人卻喜歡使用UTF8編碼字符,所以需要在UTF8與UNICODE之間相互轉換,而我在2010年12月7日寫的一個字符轉換函式庫剛好派上用場.所有轉換MultiByteToWideChar()與WideCharToMultiByte()兩個函式完成,轉換後以NULL字符結尾.特將其簡化並記錄如下,便於以後移植使用.
多字節字符(ANSI/UTF-8)轉換寬字符(UNICODE)
int MultiByteToWideChar(
UINT CodePage, // 代碼頁
DWORD dwFlags, // 字符標誌, 默認設為0
LPCSTR lpMultiByteStr, //多字節字符
int cchMultiByte, //多字節字符個數
LPWSTR lpWideCharStr, // 寬字符輸出緩存
int cchWideChar //寬字符緩存大小
);
寬字符(UNICODE)轉換多字節字符(ANSI/UTF-8)
int WideCharToMultiByte(
UINT CodePage, //代碼頁
DWORD dwFlags, // 字符標誌, 默認設為0
LPCWSTR lpWideCharStr, // 寬字符
int cchWideChar, //寬字符長度
LPSTR lpMultiByteStr, //多字節字符輸出緩存
int cchMultiByte, //多字節字符緩存輸出大小
LPCSTR lpDefaultChar, // 自定義寬字符,默認設為NULL
LPBOOL lpUsedDefaultChar // 是否使用寬字符
);
//——————————————————————
// Ansi轉換Unicode
// Unicode:Unicode碼文本輸出
// Unicode_Size:Unicode碼輸出緩衝區WORD的長度
// Ansi:ANSI碼文本輸入,以NULL字符接尾
// Encode:ANSI文本字符編碼
// 返回值:Unicode 字符個數!(Unicode一個字符需兩個字節)
//——————————————————————
int Ansi_To_Unicode(WCHAR * Unicode,int Unicode_Size,char * Ansi,int Encode)
{
int Unicode_Length;// Unicode 字符個數!非字節數!
if(Unicode == NULL || Ansi == NULL)
return 0;
// Ansi轉換Unicode
Unicode_Length = MultiByteToWideChar(Encode, NULL, Ansi,strlen(Ansi), Unicode, Unicode_Size);// 轉換
Unicode[Unicode_Length] = 0;
return Unicode_Length;
}
//——————————————————————
//Unicode轉換Ansi
//Ansi:ANSI碼文本輸出
//Unicode_Size:Unicode碼輸出緩衝區WORD的長度
//Unicode:Unicode碼文本輸入
//返回值:Ansi所占字節數!
//——————————————————————
int Unicode_To_Ansi(char* Ansi,int Ansi_Size,PWORD Unicode)
{
int Ansi_Length;
if(Ansi == NULL || Unicode == 0)
return 0;
//Unicode轉換Ansi
Ansi_Length = WideCharToMultiByte(CP_ACP, NULL, Unicode, wcslen(Unicode), Ansi, Ansi_Size, NULL, NULL);
Ansi[Ansi_Length] = NULL;
return Ansi_Length;
}
//——————————————————————
// UTF-8 轉 Unicode
//Unicode:Unicode碼文本輸出
//Unicode_Size:Unicode碼輸出緩衝區WORD的長度
//Utf8:Utf-8文本輸入
//返回值:UTF-8字符個數!
//——————————————————————
int Utf8_To_Unicode(WCHAR * Unicode,int Unicode_SIze,char * Utf8)
{
int Unicode_Length;
if(Utf8 == NULL || Unicode == NULL )
return 0;
// UTF-8 轉 Unicode
Unicode_Length = MultiByteToWideChar(CP_UTF8, NULL, Utf8, strlen(Utf8), Unicode, Unicode_SIze);
Unicode[Unicode_Length] = NULL;
return Unicode_Length;
}
//——————————————————————
// UTF-8 轉 Unicode
//Utf8:UTF-8字符輸出
//Utf8_Size:UTF-8碼輸出緩衝區BYTE的長度
//Unicode:Unicode寬字符輸入
//返回值:Unicode所占字節數!
//——————————————————————
int Unicode_To_Utf8(char * Utf8,int Utf8_Size,WCHAR * Unicode)
{
int Utf8_Length;
if(Utf8 == NULL || Unicode == NULL)
return 0;
// UTF-8 轉 Unicode
Utf8_Length = WideCharToMultiByte(CP_UTF8, NULL, Unicode, wcslen(Unicode), Utf8, Utf8_Size, NULL, NULL);
Utf8[Utf8_Length] = NULL;
return Utf8_Length;
}
//—————————————————————————
//Ansi 轉 Utf8
//Utf8:UTF-8字符輸出
//Utf8_Size:UTF-8碼輸出緩衝區BYTE的長度
//Ansi:ANSI文本輸入
//Encode:ANSI文本字符編碼
//返回值:Utf8字節長度
//—————————————————————————
int Ansi_To_Utf8(char * Utf8,int Utf8_Size,char * Ansi,int Encode)
{
int Utf8_Length = NULL;
PWORD Unicode;
int Unicode_Size;
int Unicode_Length;
Unicode = (PWORD)Utf8;
Unicode_Size = Utf8_Size/2;
// Ansi 轉 Unicode
//Unicode_Length = Ansi_To_Unicode(Unicode,Unicode_Size,Ansi,Encode);
Unicode_Length = MultiByteToWideChar(Encode, NULL, Ansi,strlen(Ansi), Unicode, Unicode_Size);// 轉換
Unicode[Unicode_Length] = 0;
// Unicode 轉 Utf8
//Utf8_Length = ::Unicode_To_Utf8(Utf8,Utf8_Size,Unicode);
Utf8_Length = WideCharToMultiByte(CP_UTF8, NULL, Unicode, wcslen(Unicode), Utf8, Utf8_Size, NULL, NULL);
Utf8[Utf8_Length] = NULL;
return Utf8_Length;
}
//—————————————————————————
// Utf8 轉換 Ansi
// Ansi: ANSI文本輸出
// Ansi_Size:ANSI碼輸出緩衝區BYTE的長度
// Utf8: UTF-8字符輸入
// 返回值:Ansi字節長度
//—————————————————————————
int Utf8_To_Ansi(char * Ansi,int Ansi_Size,char * Utf8)
{
int Ansi_Length = NULL;
PWORD Unicode;
int Unicode_Size;
int Unicode_Length;
Unicode = (PWORD)Ansi;
Unicode_Size = Ansi_Size/2;
// Utf8 轉 Unicode
//Unicode_Length = Utf8_To_Unicode(Unicode,Unicode_Size,Utf8);
Unicode_Length = MultiByteToWideChar(CP_UTF8, NULL, Utf8, strlen(Utf8), Unicode, Unicode_Size);
Unicode[Unicode_Length] = NULL;
// Unicode 轉 Ansi
//Ansi_Length = ::Unicode_To_Ansi(Ansi,Ansi_Size,Unicode);
Ansi_Length = WideCharToMultiByte(CP_ACP, NULL, Unicode, wcslen(Unicode), Ansi, Ansi_Size, NULL, NULL);
Ansi[Ansi_Length] = NULL;
return Ansi_Length;
}
| 編碼類型 | 數值 | 說明 |
| CP_ACP | 0 | 默認ANSI代碼頁 |
| CP_OEMCP | 1 | 默認OEM代碼頁 |
| CP_MACCP | 2 | 默認MAC代碼頁 |
| CP_THREAD_ACP | 3 | 本線程ANSI代碼頁 |
| CP_SYMBOL | 42 | SYMBOL轉換 |
| CP_UTF7 | 65000 | UTF-7轉換 |
| CP_UTF8 | 65001 | UTF-8轉換 |
| CP_ANSI | 1252 | 通用ANSI 代碼頁 |
| ISO_8859_1 | 28591 | 西歐語言 |
| ARABIC | 1256 | 阿拉伯語 |
| GENERAL | 1252 | 通用 |
| DUTCH | 1252 | 荷蘭,德國 |
| CZECH | 1250 | 捷克斯洛伐克 |
| HUNGARIAN | 1250 | 匈牙利 |
| ICELANDIC | 1252 | 冰島 |
| NORDIC | 1252 | 北歐日耳曼民族的 |
| NORWDAN | 1252 | |
| POLISH | 1250 | 波蘭 |
| CYRILLIC | 1251 | 西裏爾字母 |
| SPANISH | 1252 | 西班牙 |
| SWEDFIN | 1252 | |
| TURKISH | 1254 | 土耳其語, 突厥語族 |
| GREEK | 1253 | 希臘 |
| HEBREW | 1255 | 希伯來語 |
| JAPANESE | 932 | 日本 |
| KOREAN | 949 | 朝鮮 |
| BIG5 | 950 | 正體中文 |
| GB2312 | 936 | 簡體中文 |
| GBK | 936 | 簡體中文 |
| GB18030 | 54936 | 簡體中文 |
| SLOVENIAN | 1250 | 未開發 |

近日寫SEO應用程式,因現在目錄路徑可能會有中文字符或非ASCII字符,所以使用寬字符版的程式,但出現_T()與_TEXT()宏指令無定義:
error C2065: ‘_T’ : undeclared identifier
又不想直接使用L()宏指令定義寬自字符,百思不得其解.原來_T()與_TEXT()宏指令的定義在TCHAR.H文件,添加#include <TCHAR.h>即可解決.
VC使用#define _MBCS定義則使用ANSI字符,而定義#define _UNICODE 則使用UNICODE寬字符.如過想全局定義_MBCS或_UNICOD可在Settings設置如上圖.
Project Settings/C/C++/Category/General/Preprocessor definitions/ WIN32,_DEBUG,_WINDOWS,_UNICODE

我果台雜牌平板更換電池後獲得新的生命.平板本為雙系統Win8+Android.因為硬盤只有64GB再分給兩系統使用可利用率實在太低.故想重新分區安裝Win10.在微軟下載Windows10 ISO官方鏡像.版本號為1709居然無法安裝第三應用,只可以安裝在應用商店下載的應用或者購買專業版…暈!也就想激活Win10都無可能.之後安裝早期的Win10-ISO鏡像才成攻激活.

Photoshop快捷鍵完整版
以前有去外面上課與買書自學Photoshop,但一直只懂皮毛未能入門,因為現在天天寫BLOG要用到Photoshop,所以把快捷鍵匯總成列表
| 工具箱快捷鍵 | 簡介 |
| V鍵 | 移動工具 |
| CTRL鍵 | 按下Ctrl鍵切換為移動工具 |
| I鍵 | 吸管與顏色取樣器 |
| ALT鍵 | 按下Alt鍵切換為吸色工具,視版本而定 |
| H鍵 | 抓手工具 |
| SPACE(空格)鍵 | 按下空格切換為抓手工具 |
| T鍵 | 文字工具(橫排文字, 橫排文字蒙板,直排文字,直排文字蒙板) |
| Z鍵 | 縮放工具
按下ALT變縮小否則為放大 |
| Ctrl鍵++鍵 | 放大 |
| Ctrl鍵+-鍵 | 縮小 |
| F鍵 | 標準螢幕模式,帶有功能表欄的全屏模式,全屏模式,之間切換,此鍵要切記 |
| A鍵 | 直接選取工具 |
| M鍵 | 選框工具 |
| C鍵 | 裁剪工具 |
| L鍵 | 套索、多邊形套索、磁性套索 |
| +鍵 | 套索模式下放大 |
| -鍵 | 套索模式下縮小 |
| W鍵 | 魔棒工具 |
| J鍵 | 噴槍工具 |
| B鍵 | 畫筆,鉛筆工具 |
| [鍵 | 畫筆或鉛筆直徑縮小 |
| ]鍵 | 畫筆或鉛筆直徑擴大 |
| S鍵 | 像皮圖章、圖案圖章 |
| Y鍵 | 歷史記錄畫筆工具,歷史記錄藝術畫筆 |
| E鍵 | 像皮擦工具 |
| N鍵 | 鉛筆,直線工具 |
| R鍵 | 模糊,銳化,塗抹工具 |
| O鍵 | 減淡,加深,海棉工具 |
| P鍵 | 鋼筆,自由鋼筆,磁性鋼筆 |
| U鍵 | 矩形,圓角矩形,錐圓,多邊形,直線,自定形狀工具 |
| G鍵 | 油漆桶,直線漸變,徑向漸變,對稱漸變,角度漸變,菱形漸變 |
| K鍵 | 切片工具,切片選取工具 |
| D鍵 | 設置默認前景色和背景色 |
| X鍵 | 切換前景色和背景色 |
| Q鍵 | 切換標準模式和快速蒙板模式 |
| 0至9 | 設置圖層透明度,當前工具不接受數字鍵時有效
0為不透明 1至9透明度 |
| 視圖快捷鍵 | 簡介 |
| CTRL鍵+Y鍵 | 校驗顏色 |
| CTRL鍵+SHIFT鍵+Y鍵 | 色域警告 |
| CTRL鍵++鍵 | 放大 |
| CTRL鍵+-鍵 | 縮小 |
| CTRL+0鍵 | 滿畫布顯示 |
| CTRL+ALT+0鍵 | 按實際圖元顯示 |
| CTRL+H鍵 | 顯示/隱藏選擇區域 |
| Ctrl鍵+Shift鍵+H鍵 | 顯示/隱藏路徑 |
| CTRL鍵+ALT鍵+’鍵 或 Ctrl鍵+”鍵 | 顯示/隱藏網格 |
| CTRL鍵+R鍵 | 顯示/隱藏標尺 |
| CTRL鍵+;鍵 | 顯示/隱藏參考線 |
| CTRL鍵+ALT鍵+;鍵 | 鎖定/解鎖參考線 |
| F5鍵 | 顯示/隱藏“畫筆”面板 |
| F6鍵 | 顯示/隱藏“顏色”面板 |
| F7鍵 | 顯示/隱藏“圖層”面板 |
| F8鍵 | 顯示/隱藏“資訊”面板 |
| F9鍵 | 顯示/隱藏“動作”面板 |
| TAB鍵 | 顯示/隱藏所有命令面板,此命令要緊記 |
| Shift鍵+TAB鍵 | 顯示或隱藏工具箱以外的所有調板 |
| 選擇快捷鍵 | 簡介 |
| CTRL鍵+A鍵 | 全選 |
| CTRL鍵+D鍵 | 取消選擇 |
| CTRL鍵+SHIFT鍵+I鍵 | 反選 |
| CTRL鍵+ALT鍵+D鍵 | 羽化 |
| CTRL鍵+SHIFT鍵+D鍵 | 不明操作 |
| 編輯快捷鍵 | 簡介 |
| CTRL鍵+Z鍵 | 撤銷與恢復迴圈切換 |
| CTRL鍵+SHIFT鍵+Z鍵 | 撤銷操作 |
| CTRL鍵+ALT鍵+Z鍵 | 恢復操作 |
| CTRL鍵+X鍵 | 剪切 |
| CTRL鍵+C鍵 | 複製 |
| CTRL鍵+SHIFT鍵+C鍵 | 在選框中複製 |
| CTRL鍵+V鍵 | 粘貼 |
| CTRL鍵+SHIFT鍵+V鍵 | 粘到選框中 |
| CTRL鍵+T鍵 | 自由變換,最常的快捷鍵 |
| ENTER鍵 | 在自由變換模式下應用自由變換 |
| CTRL鍵 | 在自由變換模式下扭曲 |
| ALT鍵 | 在自由變換模式下從中心或對稱點開始變換 |
| SHIFT鍵 | 在自由變換模式下限制 |
| ESC鍵 | 在自由變換模式下取消變形 |
| CTRL鍵+SHIFT鍵+T鍵 | 自由變換複製的象素資料 |
| CTRL鍵+SHIFT鍵+ALT鍵+T鍵 | 再次變換複製的象素資料並建立一個副本 |
| DEL鍵 | 刪除選框中的圖案或選取的路徑 |
| CTRL鍵+BackSpace(退格)鍵或CTRL鍵+DELETE鍵 | 用背景色填充所選區域或整個圖層 : |
| ALT鍵+BackSpace(退格)鍵或ALT鍵+DELETE鍵 | 用前景色填充所選區域或整個圖層: |
| SHIFT鍵+BackSpace(退格)鍵 | 彈出“填充”對話方塊 |
| CTRL鍵+ALT鍵+Backspace(退格)鍵 | 從歷史記錄中填充 |
| CTRL鍵+SHIFT鍵+T鍵 | 再次變換 |
| CTRL鍵+SHIFT鍵+K鍵 | 色彩設置 |
| 文件快捷鍵 | 簡介 |
| CTRL鍵+N鍵 | 新建文件 |
| CTRL鍵+O鍵 | 打開文件 |
| CTRL鍵+ALT鍵+ O鍵 | 打開為 |
| CTRL鍵+W鍵 | 關閉當前圖像 |
| CTRL鍵+SHIFT鍵+W鍵 | 關閉全部視窗 |
| CTRL鍵+S鍵 | 保存當前圖像,要常用此鍵. |
| CTRL鍵+SHIFT鍵+S鍵 | 當前圖像另存為 |
| CTRL鍵+ALT鍵+S鍵 | 當前圖像另存為網頁格式 |
| CTRL鍵+ALT鍵+P鍵 | 列印設置 |
| CTRL鍵+SHIFT鍵+P鍵 | 頁面設置 |
| CTRL鍵+P鍵 | 列印當前圖像 |
| CTRL鍵+Q鍵 | 退出 |
| CTRL鍵+K鍵 | 打開“預置”對話方塊 |
| CTRL鍵+ALT鍵+ K鍵 | 顯示最後一次顯示的“預置”對話方塊 |
| CTRL鍵+1鍵 | 設置“常規”選項(在預置對話方塊中) |
| CTRL鍵+2鍵 | 設置“存儲檔”(在預置對話方塊中) |
| CTRL鍵+3鍵 | 設置“顯示和遊標”(在預置對話方塊中) |
| CTRL鍵+4鍵 | 設置“透明區域與色域”(在預置對話方塊中) |
| CTRL鍵+5鍵 | 設置“單位與尺規”(在預置對話方塊中) |
| CTRL鍵+6鍵 | 設置“參考線與網格”(在預置對話方塊中) |
| CTRL鍵+7鍵 | 設置“增效工具與暫存檔”(在預置對話方塊中) |
| CTRL鍵+8鍵 | 設置“記憶體與圖像快取記憶體”(在預置對話方塊中) |
| 圖層快捷鍵 | 簡介 |
| CTRL鍵+SHIFT+N鍵 | 新建圖層 |
| CTRL鍵+J鍵 | 複製當前圖層 |
| CTRL鍵+G鍵 | 與前一圖層編組 |
| CTRL鍵+SHIFT鍵+G鍵 | 取消編組 |
| CTRL鍵+E鍵 | 向下合併圖層 |
| CTRL鍵+SHIFT鍵+E鍵 | 合併可見圖層 |
| CTRL鍵+ALT鍵+ E鍵 | 蓋印 |
| CTRL鍵+ALT鍵+ SHIFT鍵+E鍵 | 蓋印可見圖層 |
| CTRL鍵+[鍵 | 將當前圖層下移一層 |
| CTRL鍵+]鍵 | 將當前圖層上移一層 |
| CTRL鍵+ SHIFT鍵+[鍵 | 將當前圖層移到最下麵 |
| CTRL鍵+ SHIFT鍵+]鍵 | 將當前圖層移到最上面 |
| ALT鍵+[鍵 | 選擇下一個圖層 |
| ALT鍵+]鍵 | 選擇上一個圖層 |
| Alt鍵+Shift鍵+[鍵 | 選擇底部圖層 |
| Alt鍵+Shift鍵+]鍵 | 選擇頂部圖層 |
| 0鍵至9鍵 | 設置圖層透明度,當前工具不接受數字鍵時有效
0為不透明 1至9透明度 |
| /鍵 | 鎖定/解鎖透面象素 |
| 圖像調整快捷鍵 | 簡介 |
| CTRL鍵+L鍵 | 調整色階 |
| CTRL鍵+SHIFT鍵+L鍵 | 調整自動色階 |
| CTRL鍵+SHIFT鍵+ALT鍵+L鍵 | 調整自動對比度 |
| CTRL鍵+M鍵 | 調整曲線 |
| CTRL鍵+B鍵 | 調整色彩平衡 |
| CTRL鍵+U鍵 | 調整色相/飽和度 |
| CTRL鍵+SHIFT鍵+U鍵 | 去色 |
| CTRL鍵+I鍵 | 反相 |
| CTRL鍵+ALT鍵+X鍵 | 提取 |
| CTRL鍵+SHIFT鍵+X鍵 | 液化 |
| 濾鏡快捷鍵 | 簡介 |
| CTRL鍵+F鍵 | 上次濾鏡操作 |
| CTRL鍵+SHIFT鍵+F鍵 | 消褪濾鏡操作 |
| CTRL鍵+ALT鍵+F鍵 | 重複執性上次的濾鏡操作(可調參數) : |
| 幫助快捷鍵 | 簡介 |
| F1 | 打開幫助目錄 |
Windows鍵盤快捷鍵
為什麼使用滑鼠能完成操作,還要使用鍵盤去完成?假設你右手使用滑鼠完成所有的操作,你右手會很快會過勞而受損,通過左手的配合則能分擔一半勞動強度,而且能加快工作一倍速度。
| 快捷鍵 | 功能簡介 |
| WIN或CTRL+ESC | 打開開始菜單
WIN鍵是有微軟標誌的果個按鍵. |
| WIN+E | 打開資源管理器,
這是我最常用快捷鍵之一,因為它太重要. |
| WIN+L | 快速鎖定系統
暫時離開電腦時最快的鎖定電腦的方法 |
| WIN+M | 最小化所有視窗. |
| WIN+SHIFT+M | 還原所有視窗,與WIN+M配合使用 |
| WIN+D | 最小化與還原所有視窗之間切換
這個比WIN+M更好用 |
| WIN+F | 打開查找視窗 |
| WIN+R | 打開運行視窗 |
| WIN+U | 打開輔助功能 |
| WIN+CTRL+M | |
| WIN+CTRL+F | 打開查找電腦視窗 |
| WIN+Pause Break | 打開系統屬性
比在資源管理器中打開快多了. |
| WIN+F1 | 單獨的打開幫助 |
| WIN+TAB | 迴圈切換任務欄上的按扭,但不彈出zh只切換焦點 |
| CTRL+C或CTRL+INSERT | 複製 |
| CTRL+V或SHIFT+INSERT | 粘貼 |
| CTRL+X | 剪切 |
| CTRL+S | 保存
這是使用率最高的,因為保存是好習慣 |
| CTRL+A | 全選
選擇所有文檔或文本或所有的 |
| CTRL+F | 查找
文檔內部查找最常用 |
| DELETE | 刪除,移入回收站 |
| SHIFT+DELETE | 直接刪除不移入回收站 |
| CTRL+Z | 撤銷,例如刪除後的恢復 |
| CTRL+Y | 恢復(暫不支持) |
| CTRL+P | 列印文檔 |
| CTRL+W | 關閉當前焦點視窗視窗 |
| CTRL+鼠标滚轮 | 縮小於放大
常用與網頁流覽與文檔編輯 |
| LEFT(拖放)+ CTRL | 複製文檔
LEFT滑鼠左鍵拖放文檔+ CTRL鍵 |
| LEFT(拖放)+ CTRL+SHIFT | 創建文檔的快捷方式
LEFT滑鼠左鍵拖放文檔+ CTRL鍵+ SHIFT鍵 |
| CTRL+LEFT(選擇) | 逐個選擇文檔
CTRL鍵+滑鼠左鍵選擇文檔 |
| SHIFT+LEFT(選擇) | 連續選擇文檔
SHIFT鍵+滑鼠左鍵選擇文檔 |
| CTRL+SHIFT+LEFT(選擇) | 連續逐個選擇文檔
CTRL鍵+SHIFT鍵+滑鼠左鍵選擇文檔 |
| CTRL+HOME/HOME | 移動游標到文檔的開始 |
| CTRL+END/END | 移動游標到文檔的結束 |
| ALT+F4 | 關閉分頁窗口
只能關閉內部分頁視窗 |
| CTRL+W | 關閉當前焦點視窗視窗 |
| ALT+F4 | 關閉當前焦點視窗視窗
能關閉所有視窗. |
| ALT+ESC | 在活动的窗口链中切换 |
| ALT+SHIFT | 在輸入法之間切換這是最常用快捷鍵 |
| ATL+TAB | 迴圈切換視窗
按住ATL鍵,在按TAB鍵切換視窗 |
| ATL+SHIFT+TAB | 反向迴圈切換視窗
按住ATL鍵+SHIFT鍵,在按TAB鍵反向切換視窗 |
| ALT+PRINT SCREEN | 將當前焦點窗口截圖
這是最好用截圖工具,比第三方的截圖工具更好使用 |
| PRINT SCREEN | 將當前螢幕截圖
與ALT鍵配合使用根本無需第三方的截圖工具 |
| SHIFT+F10 | 彈出當前焦點菜單 |
| SHIFT+DELETE | 直接刪除不移入回收站 |
| F1 | 説明 |
| F2 | 重命名檔案名
比滑鼠右鍵彈出功能表要好用 |
| F3 | 查找
資源管理器中使用 |
| F4 | 查閱
需與滑鼠配合使用,移動滑鼠到目標然後按F4鍵 |
| F5 | 刷新
網頁上最常用 |
| F6 | 窗口内部焦点切换 |
| F10 | 把焦點切換到菜單欄 |
| F11 | 視窗與全屏之間切換 |
| F12 | 另存為
與CTRL+S保存配合使用 |
| ESC | 取消當前任務 |

文件保險箱
文件保險箱不但可以讓別人無法看到保險箱下的內容,而且更無法刪除保險箱. 保險箱无法删除更能起到保護文件的作用,文件保險箱其實就是生成無發刪除的文件夹.只要檔夾中包含不規範字符既可.
文件保險箱
打开保险箱
删除保险箱

強制刪除文件
在使用Windows的過程中我們可能會遇到無法刪除的文件,可能原因有:
我們可以使用命令行模式強制刪除文件和目錄.
下面講述命令行的作用
edl /f /a /q \\?\%1
rd /s /q \\?\%1
第一行命令edl刪除檔,參數f強制刪除, 參數q無需確認. 參數?避免Windows檢查文件名的合法性
第二行命令rd刪除目錄,參數s強制刪除目錄和所有子目錄下的所有檔, 參數q無需確認. 參數?避免Windows檢查文件名

Windows10兼容老舊遊戲
如果想在Windows10玩老舊遊戲,嘗試更改程式兼容性,就能在全屏模式下運行.

Windows10遊戲視窗與全屏之間快速切換
遊戲視窗模式與全屏模式快速切換使用快捷鍵Alt+Enter
Dell Inspiron 15 3000 Series評測

因為媽咪去美國探她大佬隨手買台Dell Inspiron 15 3000 Series 未含稅275美元. 稅率為8%.平常媽咪自已使用.不過對於還在使用二手IBM-T60P WinXP我嚟講是見識高科技.
電源開關在鍵盤右上角.CPU是Intel Core i3 515U主頻2.1GHz發熱量很低,與T60P熱到死機形成鮮明對比,電池續航時間4小時,T60P安裝9節電芯也只能2小時.最重要重量輕外出方便.4GB-DDR3記憶體對於64位的Win10系統太小太小.
顯卡是CPU自帶共用1GB記憶體.因為本人第一部電腦就是主板自帶顯卡.所以對於自帶顯卡很反感.所以是一大敗筆.
自帶多合1讀卡器這個倒是很實用.因為SD卡很常用.
鍵盤自帶有小鍵盤,Caps Lock鍵自帶燈,而Num Lock鍵就沒有燈,這有點不方便.
1TB硬碟但沒有劃分出擴展分區,自帶光碟和說明書媽咪嫌重在美國當飛碟仍了.暈X3.開機速度超過30秒還算可以.開機速度與硬體驅動,自啟軟體和硬碟讀取速度有直接關係.我在Win98時代我見過秒開.
15寸16:9軟屏上下左右可視角度很差,而且色彩不是很好. 與『IBM-T60P』15寸硬屏無法對比.影片輸出是HDMI沒有VGA,因位本人顯示器是太陳舊沒有HDMI,所以無法連接顯示器.
其鼠標觸控屏初用有點不爽.左右鍵要下按才有反應.還是買個無線USB滑鼠.
此電腦乃中國製造,只是在地球轉了一圈.

風雨中的微軟
由蓋茨與艾倫創辦於1975年創辦微軟.他們的開發的BASIC解譯器成為行業的標準,這令微軟逐漸佔領了整個市場.
1980年微軟迎來左一次歷史的選擇,IBM選中微軟為其個人電腦(PC)編寫作業系統.
蓋茨沒有選擇自已開發,而是選擇買.
以5萬美元的價格從西雅圖的一位元程式編制者派特森手中購買,這就是後來的MS-DOS.
IBM-PC的成功使MS-DOS成為作業系統的標準.其他PC製造商都採用MS-DOS與IBM相容.微軟以每個拷貝授權使用給其他公司.
1985年發行Windows1.0,第一個圖形介面作業系統.
1987年發行Windows2.0.
1990年發行Windows3.0,為以後Windows的成功墊下基礎.
1991年由於利益的衝突,IBM與微軟解除合作關係,這講明最好的硬體都是過眼雲煙,軟體和演算法往往最後保留下來.
1993年推出Component Object Model(COM——元件物件模型),COM一種元件軟體發展技術.
COM本身並不是錯誤,錯誤的是將所有元件基於COM來開發.如ActiveX, DirectX以及OLE等.
DirectX在6.0之後在全部基於COM開發. 要講清楚COM原理要很厚書籍,但是它所提功的函數工能可能很簡單.這是種過度封裝體現.過度封裝帶來的後果很嚴重,特別是個人/團體開發.當你發現問題時往往太遲,代碼庫以經太龐大,無法修正.即使是微軟毒性也一樣.這是微軟自已飲下的慢性毒藥.
1995年微軟發佈Windows95,一個基於16位DOS的32點陣圖型系統.ORS2自帶有IE,它的成功令個人電腦成為集遊戲機,工作,上網於一體.令計算進入彩色時代.
1995年微軟推出MSN,一個曾經與QQ進行激戰產品,在大一統全球佈局的思想下失敗,2013年關閉MSN.
1998年發佈Windows98,它在Windows95基礎上改良而來.支援更多硬體,更穩定.如果你不斷安裝軟體.重裝依然是你的唯一選擇.
2000年發佈Windows Me,最後一個16位/32位元混合的Windows系統.
1993年發佈Windows NT 3.1,微軟的開發工作始於1988年,它招攬UNIX系統的開發者,開發一款純32位元的伺服器作業系統,花費5億美金.自Window ME之後微軟所有系統度基於NT架構.
NT價構具有里程碑意義.之後Window 32位元系統就是以它為基礎的.
1996年發佈Windows NT 4.0 同樣是服務版,不適合個人使用.
2000年發佈Windows 2000,原名為Windows NT 5.0 同樣是服務版,不適合個人使用. XP基於Windows 2000代碼的產品
2001年發佈Windows XP,最多使用者的作品.介面視覺極佳.啟動速度非常快(啟動速度與安裝的硬體和驅動有直接的關係),穩定性比以往的Window讀要好.硬體的相容極佳.
很多舊硬體直接裝上驅動,硬體廠商紛紛開法XP的驅動.舊版Window使用者全部改用XP.是微軟歷史上最成功的系統之一.
2003年發佈Windows Server 2003,同樣是服務版,不適合個人使用.
2006年發佈Windows Vista,這是Windows間隔時間最久的一次發佈,相隔五年
它是微軟的最失敗的作品,系統要求高,運行速度慢.要裝Vista肯定要升升級你的舊硬體.
XP配搭Office 2003已滿足日常辦公需求.用戶完全無動力升級.
2008年發佈Windows Server 2008,同樣是服務版,不適合個人使用.
2009年發佈Windows 7,它的出現令大量XP用戶升級.它的圖型介面比XP更佳.
2012年發佈Windows 8,它統一PC與平板,移動設備後.
加入應用市場,讓個人用戶,團隊,企業有一應用的發佈管道.這是微軟應該在Windows95/Windows98年代就應該做的事.
它卻等到其他移動應用市場掘起,Windows移失去移動市場.
2012年發佈Windows Server 20012,同樣是服務版,不適合個人使用.
2013年微軟宣佈收購諾基亞.這是微軟繼COM元件物件模型,應用市場後又一重大失策.
不但消耗大量資金去購買一間不思改進的硬體廠家.還令其他硬體廠商失去開發Windows移動設備的興趣.
2015年發佈Windows10,它將是所有設備統一平臺,最後一個Windows.
面對Android/安桌系統在移動市場的絕對地位,微軟卻遲遲不開發安桌java虛擬機.
這招可講是微軟的閃電鉗型戰術.
小鉗型支援安桌軟體遊戲,吸收大量安桌用戶,手機開發廠商.
大鉗型支部安桌應用市場,加入移動廣告.更加威脅到Google廣告業務.
你必須登入才能發表留言。