当前位置:  编程技术>c/c++/嵌入式
本页文章导读:
    ▪Qt实例2 - 文本编辑器(1)加入查找框      实例1我们做了一个查找框,这东西必须得配合文本才能发挥作用,所以我们再做一个很简单的文本编辑器。Qt里面有一个叫做QPlainTextEdit的东西可以实现文本编辑的功能,类似于HTML里的textarea.........
    ▪截屏上传插件开发流程      ActiveX简介  ActiveX作为一种古老的技术曾经辉煌一时,因其安全性一直被人们所诟病,现在很多功能已被其它技术   (Silverlight、Flash、html5)所取代。为什么ActiveX不安全呢?因为安装.........
    ▪.NET程序员的C\C++情结(3)      摘要这个系列是本人在工作或工作之余开发和学习C\C++的一些笔记。本文涉及C++/CLI的一些内容。本文为原创,首发于我的个人博客:.NET程序员的C\C++情结(3)。欢迎交流指正。转载请注明出处。.........

[1]Qt实例2 - 文本编辑器(1)加入查找框
    来源:    发布时间: 2013-10-14

实例1我们做了一个查找框,这东西必须得配合文本才能发挥作用,所以我们再做一个很简单的文本编辑器。

Qt里面有一个叫做QPlainTextEdit的东西可以实现文本编辑的功能,类似于HTML里的textarea。废话不多说,我们开始写代码。

 

我们用QPlainTextEdit实现文本编辑功能

1.新建一个项目,名字就叫editor吧,取消创建界面,类名默认,基类默认为MainWindow就可以了。

2.修改mainwindow.h,给他一些类和变量的声明:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
class QPlainTextEdit;
class MainWindow : public QMainWindow
{
Q_OBJECT

public:
MainWindow(QWidget *parent = 0);
~MainWindow();

private:
QPlainTextEdit *textArea;
};

#endif // MAINWINDOW_H

修改mainwindow.cpp,把声明的组件加进去:

#include "mainwindow.h"
#include <QPlainTextEdit>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(tr("MyEditor"));

//类似于html里的textarea
textArea = new QPlainTextEdit;

//设为中央部件
setCentralWidget(textArea);
}



MainWindow::~MainWindow()
{

}

点击绿色播放按钮运行一下看看效果吧,我们可以在里面写文字了:


    
[2]截屏上传插件开发流程
    来源:    发布时间: 2013-10-14

ActiveX简介

  ActiveX作为一种古老的技术曾经辉煌一时,因其安全性一直被人们所诟病,现在很多功能已被其它技术

   (Silverlight、Flash、html5)所取代。为什么ActiveX不安全呢?因为安装后它可以操作本地电脑资源,

  这就人们又爱又怕的地方,爱的是开发人员,利用它可以做很多事,很多事Web或其它技术不能做的事情,

  比如:自动读电脑的目录并上传资料,修改电脑的一些设置等。使用者怕它会不会在自己的电脑里面做一

  些坏事,比如:窃取用户电脑资料、种植木马等等。

  虽然ActiveX渐渐的在退出历史的舞台,IE对它的限制也越来越严格,但是现下还有很多地方在使用这一项技术。

  比如网上银行和一些登录安全安求比较高的网站密码框(如:淘宝)用的就是它了,文件上传,网站需验证用户

  电脑IP,MAC地址,网上视频,监控等等。

 

截屏并上传插件开发

开发原因

  从事MIS系统开发多年,在维护系统的时候,经常有一些新来的同事在使用系统时,出现一些问题。

  于是老打电话给IT的系统护人员资询,说系统出错了。系统护人员就问出现什么错误,用户有时又描述不清,

  于是要求用户截个屏看看是什么情况,或者干脆走到用户里去。有时候新人连截屏都不知道,还有怎么发给你

  看等一系列问题,IT系统护人员你是不是也经常遇到这样的问题,是不是被这样的事烦透了呀。所以一直想开

  发一个能自动截屏并上传的功能,Web不能操作客户端所以没法截屏,只能用其它技术,于是便有了开一个

  ActiveX控件截屏并上传到指定页面的想法。

 

技术选择

  自己大学入门的第一门语言便是C语,印象非常深刻,也学了一期VC好像没学到什么东西,之后就老师引入了

  VB.NET这门课,VS2002新建窗体拖控件,太强太神奇了,后来出来工作公司用的是VS2003用的是C#,自己

  也自然而然改投C#门下,一直至今。开发ActiveX控件有很多个方法,可以用VB、Delphi、C、C++等等,

  C#也能开发前提是使用ActiveX控件的客户端得装一个.NET框架,这点让人受不了。于是决定采用C++开发。

 

学习历程

  寻觅ATL开发教程。《Visual.C.6.0Active.XNathan.Wallance.pdf》这本教材作为入库级的教材相当不错,

  《ATL开发指南.pdf》这本稍深入一点。 了解一下COM,确实是一个复杂的技术,不是专业人士是很难开发的,

  我只是开一个截屏上传的功能,所以其它不相关的只是了解,也没精力深入学习冲冲越过。

  用C++开发ActiveX可采用MFC\ATL两种方式。MFC类库全开发方便快捷,但是控件体积相对来讲要大一点,

  而ATL正是为开发ActiveX而生,控件体积小,类库当然没有MFC的全了,所以很多东西得自己实现,VC5.0\6.0

  之后引用了向导开发工作简化了很多,新手也更容易入门,开发一些简单的控件应该也不再是一件很困难的事情了。

  也看了很多人写的博客教程,开始平台用的是VC6.0因为与本机总是不兼容而告吹,其实VS20XX中的Visual C++

  也是可以开发的。

 

功能分析

  1)截取客户端屏幕,这个不需要用户截取指定区域,直接抓取用户的整个屏幕即可,

     所以控件不需要界面。

  2)上传到指定的网页,所以得有网络传输的功能。

 

技术实现

  原则:尽量用最底层的类库,最好是系统自带的这样控件体积就越小安装越方便,无需引入其它dll或框架之类的。

  一、屏幕截取

  1)获取屏幕,可以通个窗口句柄,获取屏幕,也可以CreateDC创建 HDC对象等。

      2)保存操作,遇到了一个艰难的选择,一是自写实现保存为位图,如果想保存其它格式(jpg)那得写一堆代码。

          二是引入高级一点的类库,atlimage.h头文件里面有CImage这个类,一个Save指定一下格式就可以搞定。

  二、图片上传

  1)网络通讯功能最底层当然是socket了,http post 上传文件,这个得先熟悉一下http的协议,因为一直从事WEB开发,

    对个已经相当熟知了,于是用Firefox浏览器中用HttpFox抓取了上传的POST文本,按照这个拼装。socket怎么使用,

      网上搜索一番,整理一下,然后按照这个开始发数据到测试上传网页,一直不成功。拼装的字符串看了一遍又一遍,

      与协议反复核对,换行是否正确分隔线是否正确,其实在这里我范一个错,我把头部boundary的分隔线直接复制到后面

      文件分隔用了,结束后要多加--这个当然知道了,于是上网搜一个http抓包的工具 sniffer专业版,安装调式程序居然没抓

      到包,专业版太专业了不好用,也可以是自己没用习惯吧,又换一款Fiddler抓包工具,测试了一几个网址,Fiddler果然

      不错简洁不少。令人失望的是也没抓到包,开始怀念以前sniffer的一个简易版了,不管是什么数据,只要是有通讯都能抓。

      终于到了一款MiniSniffer虽然跟以前的那一款不同,但同样可以抓通讯数据, 这下终于能监控到发送的数据了,核对发送

      的数据也没错呀,悲摧了。经过几天的拆腾,放弃用socket了,继续搜寻看看C++下http通讯的有那些类,MFC下有

      CInternetSession等系列类,C++稍高层的有HINTERNET系列,ATL7.0以上提供了CAtlHttpClient类,经过筛选比

      较之后锁定用HINTERNET来开发,网上看例子看API学习,真的是被C++的类型打败了,又花了一点时学习这些类型及

      关系,不得不感叹c++的复杂与强大,原来C#的泛型在C++下早就有了,我相信应该还有很多功能其很早就有了,只是

      现在变得很加好用了,同为VS IDE下的产品与C#的编程环境就差别那么大呢? Visual C++没有提示,不会智能补全,

      删除大括不对齐,太多不方便了。又到了激动人心的时该了,调试又是不成功,这次又启用Fiddler可以监控到,也看到了

      发送的数据,核对核对。折腾了几天,到网上搜了几个例子,原原本本的的复制下来,其它也没有几个可行的,几经努力找

    到一个可行了,写法都差不多呀,后来无意中,我把头部的boundary的分线复制下与文件的分线进行对比发现了一个,令人

    兴奋的差异就是文件、控件表单名分隔多了两个--,修改后哇成功了。回头把socket做的方案修改了一下也成功了。最后就是

     接收返回的信息,需要把char字符转换成UTF-8就行了,socket收接信息包含了http信息,需要把头截取返回信息体即可,

     c/c++毕竟不是很熟识,操作也没高级语言方便所最的采用了HINTERNET的实现,图片保存也用CImage这个类,

       最终功能完成。

      小结:自已对http协议看得不是太仔细,一个细小的错误,导致花费具多的时间,不过也学到了很多东西。

           还有就是越高级的类越好用。

功能测试

    1、正常测试

    网页一加载调用,截屏上传OK一切正常。

        2、压力测试

            去掉提示按住F5不放(其实可在js里面写个循环的),一张张截屏不断的出现在upload文件夹里面,不错,

    打开Windows任务管理器,CPU时高时低正常,内存不断在增加,关闭IE内存恢正常,不这个太满意。

    3、异常测试

     1)传入错的url,返回找不资源正常返回,再刷新出错IE崩了。

     2)网络断开,报错正常返回异常,再刷新出错IE崩了。

     3)网站停掉,报错正常返回异常,再刷新出错IE崩了。

   小结:内存增加关键资源未释放、或对c/c++的char/char[]/指针等的错误使用,IE崩溃发现在异常抛出,提示堆栈异常,

      有个BSTR*的返回类型,对BSTR类型赋值错误操作所致。错误用法 *pVal=L"有异常";正确用法使用:

      :SysAllocString赋值。前前后后修改与优化再测试用了几天最后一切正常了。

 

系统发布

          ActiveX有这么几种后缀dll、exe、ocx等,为了便于用户安装或网络传输,一般需要打包成cab压缩包,最后就是签名

    
[3].NET程序员的C\C++情结(3)
    来源:    发布时间: 2013-10-14
摘要

这个系列是本人在工作或工作之余开发和学习C\C++的一些笔记。本文涉及C++/CLI的一些内容。

本文为原创,首发于我的个人博客:.NET程序员的C\C++情结(3)。欢迎交流指正。转载请注明出处。

虽然现在主要从事.NET平台的开发,但是一直以来对C\C++有着那份难以割舍的情结。本文会涉及到托管C++的一些随笔记录。

当然,如果写纯.NET应用的话,C#无疑是最合适的语言的。但是托管C++在同时处理Native调用和托管调用上无疑是十分吸引人的,往往用来作为托管世界和Native世界的桥梁。当然。你可以说用.NET的“平台调用”特性同样能够胜任,萝卜青菜各有所爱吧。

 

托管C++基础语言特性

在托管C++中需要像下面这样定义一个托管类型

public ref class ARSession
{
public:
 property UInt32 FieldId;
}

默认情况下这样的类是默认实现IDisposable的,原因很简单,既然用到C++来封装托管类型,那么八成类型需要涉及到非托管对象,实现IDisposable减少了出错的可能。可以同时实现两种“析构函数”:

!ARSession(void)
~ARSession(void)

前者是好比Dispose(),后者是C++原生的析构函数。

可以同时引用托管的命名空间和C++命名空间

using namespace System;
using namespace System::Collections::Generic;
using namespace std;

也可以向普通C++一样#include头文件,编译的过程可以理解成跟本地C++的编译过程一样,只是在编译的时候会有/clr开关,并至少引用相应的托管dll:mscorlib.dll

对于托管类型,在类型的标识右使用”^”标注,比如:

String^
array<String^>^
List<AREntry^>^

但注意,对于Nullable的值类型,使用

Nullable<UInt32>

而不是

Nullable<UInt32>^

前者在C#中会看到是uint?,而后者在C#中会看到是ValueType

 

托管C++支持类似C#中的ref

Int32% totalMatch

out的话需要加一个Attribute

using namespace System::Runtime::InteropServices;   
void foo([Out] Bar^% x);

在本地堆中申请内存是使用new关键字,而在托管堆中申请内存,使用gcnew关键字:

ARException^ exception = ARException();

 

托管C++的内存管理

上面简单介绍的一些语言特性是我实际碰到的,可能不全。与语言特性相比,更为重要的是内存管理带来的复杂性。原生的C++只有一个由C运行库管理的“本地堆”,而C++/CLI允许同时操作本地堆和托管堆。众所周知,托管堆由CLR管理,在托管堆中的内存会随时被CLR回收和压缩,这意味着,如果使用C#的引用或者C++/CLI中的“Handle”(即由String^等“戴帽子的类型“声明的变量)来操作托管堆的内存,不会有任何问题,因为CLR会自动更改引用或Handle指向的地址。然而,如果在本地堆或者栈上的本地指针来指向托管堆上的内存的话,CLR不会对压缩内存带来的地址修改负任何责任。如果发生这种情况的话,再次使用该指针将导致内存违规。下面这张图可以解释这个现象(图片来源http://www.codeproject.com/Articles/17817/C-CLI-in-Action-Using-interior-and-pinning-pointer):

在上图中,本地指针指向的地址本来是Data,但是当CLR的GC工作后,Data可能被压缩至托管堆的其他地方,而取而代之的是另外一块内存。很典型的情况就是,我们要在托管的byte[]和非托管的usigned char*对象之间传递内存,下面这段代码将String对象转化成以UTF8编码的字节数组:

char* MarshalStringCopyToChar(String^ Source)
{
   if(String::IsNullOrEmpty(Source))
       return NULL;
  
    
最新技术文章:
 




特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3