存档

2014年11月 的存档

win8.1中Hyper-V虚拟机无法初始化

2014年11月21日 没有评论

最近微软发布了Visual Studio 2015 Preview 版本,网络上对于跨平台支持是各种赞美。衣服自己洗就琢磨着要不也先下载用用看。恰好有看关于Hyper-V的文章,就顺便用这个了,VMWare 的东西就懒得下载了,于是就走上了不归路。

当初就是因为我的Y450的CPU不支持虚拟化,用不了Hyper-V,所以才换用现在的Y510P。

新建了win7的虚拟机,一路畅通,然后启动虚拟机,直接就报错,提示虚拟机无法初始化。我记得当初刚装完系统时,Hyper-V是可以用的,不知道是不是我中间做系统优化修改了什么,导致现在出错。而且也没有更具体的信息可以参考。

网上是各种搜索,有很多人也和我是一样的问题,但几乎是千篇一律的答复,请检查BIOS是否开启了虚拟化操作等等。我确认我的i7的CPU是支持的,不甘心,只好打开装*外挂,搜索到了更详细的信息,而且有解决方法,但是他们是Windows Server 2008,对此的解决方案就是升级到 SP1。微软也给出了补丁,估计这个补丁最后也收录在 SP1里了。在微软的文档里提到这个问题,出错后会在事件查看器里Microsoft\Windows\Hyper-V Worker 下生成事件ID为3040的错误信息。

但是,我的机器是win8.1,不是Windows Server 2008,抱着试一试的想法,把微软的那个补丁下载回来安装,提示签名不正确,看来不能这么用。

Hyper-V Worker、3040,这已经是一个很好的提示了,于是拿这个信息重新搜索,再选择和Win8.1系统有关,没有多少收获。

白天晚上都时不时搜索一把,代码都没有怎么写,就酱紫一周时间过去了。

对于虚拟的win7而言,其实大可不必非得坚持用Hyper-V,但是对于 Windows Phone的程序,模拟器也无法初始化,这就是个大问题了。

昨天就在衣服自己洗很是崩溃的时候,突然在网上发现了一个帖子,并最终解决了问题。

以管理员权限在命令行里执行 net Localgroup administrators SERVICE /delete

然后重启电脑,重启后win7虚拟机倒是正常了,但是Windows Phone 模拟器还是不行,重新修复了下VS,一切都看起来OK。

刚才的命令是从管理员用户组里删除 Service 用户,虽然很奇怪为什么要这么做,可删除后确实就有效果了,原文帖子里大家也是一样的疑惑。再次在事件查看器里看到到对应的事件所有者是System了,而不是原来的NT Virtual Machine。

希望对大家有用,以上。

c#创建大于屏幕尺寸的窗体

2014年11月16日 没有评论

最近的一个星期,衣服自己洗一直在折腾一件事情,最终才得以解决,现在拿出来和大家分享。

问题是这样的,如何生成一个winform 窗体,使得它的尺寸要比当前屏幕还要大。

我是在 c# 中碰到的,但是对于其它语言应该也是一样的。开始的时候我也为是MDI的限制,后来发现这个限制对一般窗体都适用,网上资料也显示,对于窗体的尺寸设置,无论是 Size 还是单独的宽度、高度,如果超过了屏幕的尺寸,系统会自动给截断。

例如,对于1366*768 分辨率、100%的DPI,如果你创建了一个窗体,并设置其尺寸为 1400*900,那么最终的窗体尺寸会是 1478*780,多余的就不显示了,当然也不会崩溃。系统对于宽度和高度会允许多添加 12像素。如果是 125%的DPI,那么这个值是 16像素。但是不会允许更多。

由于对于windows桌面应用程序驾驭能力的不足,只好请教他人。对于这个问题,大家集中表现为两种情况,一种是表示从来没有接触过MDI表示不会,毕竟是从MDI程序发现的;另外的尝试一把发现确实不太好解决劝我放弃。只好自己一个人坚持下去寻找原因。

我相信这个需求一定是可以实现,并且很简单,只是我暂时没有找到方法而已。

后来看到一个Delphi的程序实现了我想要的效果,我通过spy++比较程序间的差异,并辗转和人家交流才明白,原来是要去掉一个样式并重新设置大小。但是我这边一直没有效果。后来才发现是常量声明错误,我给设置成负值了。汗~

首先,获取窗体的当前样式,然后去掉WS_THICKFRAME样式,之后再重新设置窗体的位置和尺寸即可。如我开始所想,确实很简单,只是想到这里不太容易。如果是 c++ 之类的语言,可以在窗体(包括MDI窗体)构造的时候设置就可以了,c# 给封装起来了,所以只好放后面设置。

申明如下:

[DllImport(“user32.dll”, SetLastError = true, CharSet = CharSet.Auto)]
public static extern int SetWindowLong(IntPtr hwnd, int nIndex, int newLong);

[DllImport(“user32.dll”, SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetWindowLong(IntPtr hwnd, int nIndex);

[DllImport(“user32.dll”)]
public static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int width, int height, int flags);

[DllImport(“shell32.dll”)]
public static extern IntPtr ShellExecute(IntPtr hwnd,string lpOperation,string lpFile,string lpParameters,string lpDirectory,int nShowCmd);

public static int GWL_STYLE = (-16);
public static int WS_THICKFRAME = 262144;
public static int HWND_TOP = 0;
public static int SWP_SHOWWINDOW = 64;
public static int SW_SHOW = 5;

封装起来,这样调用会比较方便,
public void SetNewSize(int width, int height)
{
int style = GetWindowLong(this.Handle, GWL_STYLE);

SetWindowLong(this.Handle, GWL_STYLE, style & ~WS_THICKFRAME);
SetWindowPos(this.Handle, HWND_TOP, 0, 0, width, height, SWP_SHOWWINDOW);
}

最后说几个小细节作为结尾吧,对于c#而言,这个调用不能放在构造函数里,因为会被后面系统自动设置给覆盖掉,应该在 frmChild.Show()之后才有效。衣服自己洗这里也是坑了很久。另外大家可以看代码是如何去掉WS_THICKFRAME样式的,还可以思考下为什么要先获取窗体样式而不直接设置。

这下算是解决了心里的一个疙瘩,不知道做技术的是不是都这样。

分类: 日常 标签: , , ,