そういうときは有線LANにすればいいわけだが、自分が使っているDell Venue 8 ProはMicro USBコネクタで充電とUSB接続を兼ねる方式で、充電と(USBを介した)有線LANを同時使用できない(全く不可能ではないが、純正オプションの"Dell Micro USB Dongle for Data and Charging"は日本で売ってないので、ケーブルを自作したりすることが必要)。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ズーム/ムーブできるようにするには、これも定番ですがListViewをScrollViewerで囲みます。その準備として、ScrollViewerに関係する処理をBehaviors SDK (XAML)のビヘイビア(要はBlendのビヘイビア)にまとめることにします。これは参照設定 -> 参照の追加 -> Windows 8.1 -> 拡張から追加できます。
作成したビヘイビアの基本部分は以下のようなものです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
publicstaticVersionGetOsVersionByGetVersionEx(){var info =new OSVERSIONINFOEX();
info.dwOSVersionInfoSize =(uint)Marshal.SizeOf(info);var result =GetVersionEx(ref info);return result
?newVersion((int)info.dwMajorVersion,(int)info.dwMinorVersion):null;}
マニフェストファイルのcompatibilityにWindows 10のIDを含めている。
<compatibilityxmlns="urn:schemas-microsoft-com:compatibility.v1"><application><!-- The ID below indicates application support for Windows 7 --><supportedOSId="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/><!-- The ID below indicates application support for Windows 8 --><supportedOSId="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/><!-- The ID below indicates application support for Windows 8.1 --><supportedOSId="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/><!-- The ID below indicates application support for Windows 10 --><supportedOSId="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/></application></compatibility>
RtlGetVersion
publicstaticVersionGetOsVersionByRtlGetVersion(){var info =new OSVERSIONINFOEX();
info.dwOSVersionInfoSize =(uint)Marshal.SizeOf(info);var result =RtlGetVersion(ref info);return(result ==0)// STATUS_SUCCESS?newVersion((int)info.dwMajorVersion,(int)info.dwMinorVersion):null;}
NetWkstaGetInfo
publicstaticVersionGetOsVersionByNetWkstaGetInfo(){IntPtr buff =IntPtr.Zero;try{var result =NetWkstaGetInfo(null,100,out buff);if(result ==0)// NERR_Success{var info =(WKSTA_INFO_100)Marshal.PtrToStructure(buff,typeof(WKSTA_INFO_100));if(info.platform_id ==500)// PLATFORM_ID_NTreturnnewVersion((int)info.ver_major,(int)info.ver_minor);}}finally{if(buff !=IntPtr.Zero)NetApiBufferFree(buff);}returnnull;}
[修正]
IntPtrをNetApiBufferFreeで解放するよう修正した。
WMI
publicstaticVersionGetOsVersionByWmi(){var searcher =newManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");var os = searcher.Get().Cast<ManagementObject>().FirstOrDefault();if((os !=null)&&(os["OsType"]!=null)&&(os["Version"]!=null)){if(os["OsType"].ToString()=="18")// WINNTreturnnewVersion(os["Version"].ToString());}returnnull;}
VerifyVersionInfo
引数majorとminorでバージョン番号を指定し、それとの比較をする形。
publicstaticbool?IsOsEqualOrNewerByVerifyVersionInfo(int major,int minor){var info =new OSVERSIONINFOEX();
info.dwMajorVersion =(uint)major;
info.dwMinorVersion =(uint)minor;
info.dwOSVersionInfoSize =(uint)Marshal.SizeOf(info);ulong cm =0;
cm =VerSetConditionMask(cm, VER_MAJORVERSION, VER_GREATER_EQUAL);
cm =VerSetConditionMask(cm, VER_MINORVERSION, VER_GREATER_EQUAL);var result =VerifyVersionInfoW(ref info, VER_MAJORVERSION | VER_MINORVERSION, cm);if(result)returntrue;return(Marshal.GetLastWin32Error()==1150)// ERROR_OLD_WIN_VERSION?false:(bool?)null;}
ウィンドウの左右について、それぞれ上がVisual Studio 2013、下がVisual Studio "14" CTP3で、DPI 150%の状態。
確かにアイコンが変わっている。ただ輪郭がまだぼけているところを見るに、たぶんリソースにラスターデータの画像ファイルを持っていて(Visual Studio Image Libraryには以前からサイズ別の画像が用意されている)、起動時にDPIを見て適当なサイズのものをImageコントロールに読み込み、それをImageコントロールが自動リサイズしているのではないかと思う。
この1番目の課題については引っ掛かっていたことがあって、WM_DPICHANGEDのlParamについて、これはWin32のRECT構造体で"a RECT structure that provides the size and position of the suggested window, scaled for the new DPI"とだけ説明があり、新しいDPIでのウィンドウの位置とサイズを表す四角形らしいのですが、実際に試してみると同じようにウィンドウを動かしてもその度に違った値が来るので、意味が分からず無視してました。
usingSystem;usingSystem.Collections.Generic;usingSystem.Diagnostics;usingSystem.IO;usingSystem.Linq;usingSystem.Windows.Media.Imaging;/// <summary>/// Query paths for padding/// </summary>privatestaticreadonlyList<string> queryPadding =newList<string>(){"/app1/ifd/PaddingSchema:Padding",// Query path for IFD metadata"/app1/ifd/exif/PaddingSchema:Padding",// Query path for EXIF metadata"/xmp/PaddingSchema:Padding",// Query path for XMP metadata};/// <summary>/// Edit date taken field of Exif metadata of image data./// </summary>/// <param name="source">Stream of source image data in JPG format</param>/// <param name="date">Date to be set</param>/// <returns>Byte array of outcome image data</returns>publicstaticByte[]EditDateTaken(Stream source,DateTime date){if(source ==null)thrownewArgumentNullException("source");if(date ==null)thrownewArgumentNullException("date");if(0< source.Position)
source.Seek(0,SeekOrigin.Begin);// Create BitmapDecoder for a lossless transcode.var sourceDecoder =BitmapDecoder.Create(
source,BitmapCreateOptions.PreservePixelFormat|BitmapCreateOptions.IgnoreColorProfile,BitmapCacheOption.None);// Check if the source image data is in JPG format.if(!sourceDecoder.CodecInfo.FileExtensions.Contains("jpg"))returnnull;if((sourceDecoder.Frames[0]==null)||(sourceDecoder.Frames[0].Metadata==null))returnnull;var sourceMetadata = sourceDecoder.Frames[0].Metadata.Clone()asBitmapMetadata;// Add padding (4KiB) to metadata.
queryPadding.ForEach(x => sourceMetadata.SetQuery(x,4096U));using(var ms =newMemoryStream()){// Perform a lossless transcode with metadata which includes added padding.var outcomeEncoder =newJpegBitmapEncoder();
outcomeEncoder.Frames.Add(BitmapFrame.Create(
sourceDecoder.Frames[0],
sourceDecoder.Frames[0].Thumbnail,
sourceMetadata,
sourceDecoder.Frames[0].ColorContexts));
outcomeEncoder.Save(ms);// Create InPlaceBitmapMetadataWriter.
ms.Seek(0,SeekOrigin.Begin);var outcomeDecoder =BitmapDecoder.Create(ms,BitmapCreateOptions.None,BitmapCacheOption.Default);var metadataWriter = outcomeDecoder.Frames[0].CreateInPlaceBitmapMetadataWriter();// Edit date taken field by accessing property of InPlaceBitmapMetadataWriter.
metadataWriter.DateTaken= date.ToString();// Edit date taken field by using query with path string.
metadataWriter.SetQuery("/app1/ifd/exif/{ushort=36867}", date.ToString("yyyy:MM:dd HH:mm:ss"));// Try to save edited metadata to stream.if(metadataWriter.TrySave()){Debug.WriteLine("InPlaceMetadataWriter succeeded!");return ms.ToArray();}else{Debug.WriteLine("InPlaceMetadataWriter failed!");returnnull;}}}
usingSystem;usingSystem.Collections.Generic;usingSystem.ComponentModel;usingSystem.Diagnostics;usingSystem.Linq;usingSystem.Runtime.InteropServices;/// <summary>/// A partial wrapper class for Restart Manager API/// </summary>/// <remarks>/// This class is based on http://msdn.microsoft.com/en-us/magazine/cc163450.aspx/// To use this class, OS has to be Windows Vista or newer./// </remarks>publicstaticclassRestartManager{#region "Win32"// Start a Restart Manager session.[DllImport("Rstrtmgr.dll",CharSet=CharSet.Unicode)]privatestaticexternuintRmStartSession(outuint pSessionHandle,uint dwSessionFlags,string strSessionKey);// End a Restart Manager session.[DllImport("Rstrtmgr.dll")]privatestaticexternuintRmEndSession(uint dwSessionHandle);// Register target files to a Restart Manager session.[DllImport("Rstrtmgr.dll",CharSet=CharSet.Unicode)]privatestaticexternuintRmRegisterResources(uint dwSessionHandle,uint nFiles,string[] rgsFilenames,uint nApplications,
RM_UNIQUE_PROCESS[] rgApplications,uint nServices,string[] rgsServiceNames);// Get processes using target files with a Restart Manager session.[DllImport("Rstrtmgr.dll")]privatestaticexternuintRmGetList(uint dwSessionHandle,outuint pnProcInfoNeeded,refuint pnProcInfo,[In,Out] RM_PROCESS_INFO[] rgAffectedApps,outuint lpdwRebootReasons);[StructLayout(LayoutKind.Sequential)]privatestruct RM_UNIQUE_PROCESS
{publicuint dwProcessId;publicSystem.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;}[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]privatestruct RM_PROCESS_INFO
{public RM_UNIQUE_PROCESS Process;// CCH_RM_MAX_APP_NAME + 1 = 256[MarshalAs(UnmanagedType.ByValTStr,SizeConst=256)]publicstring strAppName;// CCH_RM_MAX_SVC_NAME + 1 = 64[MarshalAs(UnmanagedType.ByValTStr,SizeConst=64)]publicstring strServiceShortName;public RM_APP_TYPE ApplicationType;publicuintAppStatus;publicuintTSSessionId;[MarshalAs(UnmanagedType.Bool)]publicbool bRestartable;}privateenum RM_APP_TYPE
{/// <summary>/// The application cannot be classified as any other type./// </summary>RmUnknownApp=0,/// <summary>/// A Windows application run as a stand-alone process that displays a top-level window./// </summary>RmMainWindow=1,/// <summary>/// A Windows application that does not run as a stand-alone process and does not display a top-level window./// </summary>RmOtherWindow=2,/// <summary>/// The application is a Windows service./// </summary>RmService=3,/// <summary>/// The application is Windows Explorer./// </summary>RmExplorer=4,/// <summary>/// The application is a stand-alone console application./// </summary>RmConsole=5,/// <summary>/// The process may be a critical process and cannot be shut down./// </summary>RmCritical=1000}privateconstuint ERROR_SUCCESS =0;privateconstuint ERROR_MORE_DATA =234;#endregion/// <summary>/// Check if any process is using a specified file./// </summary>/// <param name="filePath">Path of target file</param>/// <returns>True if using</returns>publicstaticboolIsProcessesUsingFile(string filePath){bool isUsing =false;foreach(var proc inEnumerateProcessesUsingFiles(new[]{ filePath })){if(proc ==null)continue;
isUsing =true;
proc.Dispose();}return isUsing;}/// <summary>/// Enumerate processes using specified files./// </summary>/// <param name="filePaths">Paths of target files</param>/// <returns>Processes using target files</returns>/// <remarks>Caller is responsible for disposing the processes.</remarks>publicstaticIEnumerable<Process>EnumerateProcessesUsingFiles(param string[] filePaths){if((filePaths ==null)||!filePaths.Any())yieldbreak;if(!OsVersion.IsVistaOrNewer)yieldbreak;uint sessionHandle =0;// Handle to Restart Manager sessiontry{// Start a Restart Manager session.var result1 =RmStartSession(out sessionHandle,0,Guid.NewGuid().ToString("N"));if(result1 != ERROR_SUCCESS)thrownewWin32Exception("Failed to start a Restart Manager session.");// Register target files to the session.var result2 =RmRegisterResources(
sessionHandle,(uint)filePaths.Length,
filePaths,0U,null,0U,null);if(result2 != ERROR_SUCCESS)thrownewWin32Exception("Failed to register target files to a Restart Manager session.");// Get processes using target files with the session.uint pnProcInfoNeeded =0;uint pnProcInfo =0;
RM_PROCESS_INFO[] rgAffectedApps =null;uint lpdwRebootReasons;uint result3 =0;do{
result3 =RmGetList(
sessionHandle,out pnProcInfoNeeded,ref pnProcInfo,
rgAffectedApps,out lpdwRebootReasons);switch(result3){case ERROR_SUCCESS:// The size of RM_PROCESS_INFO array is appropriate.if(pnProcInfo ==0)break;// Yield the processes.foreach(var app in rgAffectedApps){Process proc =null;try{
proc =Process.GetProcessById((int)app.Process.dwProcessId);}catch(ArgumentException){// None (In case the process is no longer running).}if(proc !=null)yieldreturn proc;}break;case ERROR_MORE_DATA:// The size of RM_PROCESS_INFO array is not enough.// Set RM_PROCESS_INFO array to store the processes.
rgAffectedApps =new RM_PROCESS_INFO[(int)pnProcInfoNeeded];
pnProcInfo =(uint)rgAffectedApps.Length;break;default:thrownewWin32Exception("Failed to get processes using target files with a Restart Manager session.");}}while(result3 != ERROR_SUCCESS);}finally{// End the session.RmEndSession(sessionHandle);}}}
Disk Gazerは狭い領域の速度を細かく調べるという目的は達しましたが、これをより広い領域、あるいはディスク全体に使いたいという考えは初めからありました。問題は全領域をなめるようにリードしていくとおそろしく時間がかかることで、例えば、平均速度を100MB/sとすると1TBをリードするのに単純計算で2.8時間かかります。現在3.5インチHDDでポピュラーな4TBだと11.1時間にもなります。さすがにこれは実用的ではないです。