I have an application which renders glyphs to a printer device context. Earlier, it used GDI and it worked fine.
But now, I'm trying to use Directwrite instead.
I've changed the existing ExtTextOut call and used IDWriteTextLayout::Draw function.
I need to pass an object implementing IDWriteTextRenderer interface in the draw function.
I've implemented the DrawGlyphRun callback in IDWriteTextRenderer interface using a call to IDWriteBitmapRenderTarget:: DrawGlyphRun. So, I need to create a IDWriteBitmapRenderTarget object.
I have the following code :
IDWriteFactory* pDWriteFactory = NULL;
IDWriteGdiInterop* pGdiInterop = NULL;
IDWriteTextLayout* pTextLayout = NULL;
IDWriteBitmapRenderTarget* pBitmapRenderTarget = NULL;
IDWriteRenderingParams* pRenderingParams = NULL;
hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&pDWriteFactory));
if (!SUCCEEDED(hr))
pDWriteFactory = 0;
else
{
hr = pDWriteFactory->GetGdiInterop(&pGdiInterop);
if (!SUCCEEDED(hr))
pGdiInterop = 0;
}
hr = pGdiInterop->CreateBitmapRenderTarget((HDC)hDC, someWidth, someHeight, &pBitmapRenderTarget);
The device context hDC is being passed by a function in another dll.
Result: hr=E_FAIL
Maybe I'm missing out on something very basic, but I have little knowledge of device contexts and I'm new to DirectWrite. I need to know why the same HDC structure which is compatible with a ExtTextOut call is not being compatible with DirectWrite.
Also, since the HDC field is optional, if I pass NULL, it succeeds but nothing gets rendered by the draw function. What does passing NULL signify ?
First make sure hDC is a valid memory device context, memory part is important. NULL argument means that target creates its own context compatible with screen/desktop. In any case nothing will be rendered automatically, you need to blit yourself from HDC returned by GetMemoryDC to your context, in other words target draws to this memory DC only, and what you do next is up to you.
Related
I have added System.Messaging to my assemblies.xml cause I need to use this in my Progress OpenEdge application. However I ran into a problem.
In C# when assigning:
m.Formatter = new XmlMessageFormatter(new[] { typeof(TrowConfiguration) });
TrowConfiguration myConfiguration = m.Body as TrowConfiguration;
However I now want to do this in ABL. I first used a method to read a string and just passed a CHARACTER EXTENT 1 INITIAL "System.String" to the XmlMessageFormatter object. However I tried changing this to the path of my object, TrowConfiguration, but this doesn't work and gives me an error.
If you're looking for the System.Type reference, use
Progress.Util.TypeHelper:GetType ("<your fully qualified type name>").
I don't know why i'm having this behavior with my code coverage, maybe someone knows the reasson.
As you may know, code coverage is blue when reached, red when not reached, yellow when partially reached a line of code.
I coded a little mapper that receives a IDataReader and turns into object thanks to reflection.
internal IEnumerable<T> Convert<T>(System.Data.IDataReader dataReader) where T : new()
{
var columns = this.GetColumns(dataReader); // get a list of column name... not important.
var result = new List<T>();
while (dataReader.Read())
{
var nuevoObjeto = new T(); // <-- this line is yellow in code coverage.
foreach (var item in columns)
{
var pi = nuevoObjeto.GetType().GetProperty(item);
pi.SetValue(nuevoObjeto, dataReader[columns.IndexOf(item)]);
}
result.Add(nuevoObjeto);
}
return result;
}
As you can see, the yellow line is not a conditional like IF or WHILE... is just a simple "new T"
And if you debug this code, debug reaches very well that line, in fact test is green with expected results.
Test performs this steps.
Fake IDataReader (with nSubstitute)
Only 1 result on the datareader.
T is tested with only one TestClass... like USERTEST.
hope someone knows why this happens...
thanks!
The IL that gets generated for that line is equivalent to:
T nuevoObjeto = (default(T) == null) ? Activator.CreateInstance<T>() : default(T);
This allows structs to be used for the generic type as they satisfy the new constraint.
So, if you want 100% code coverage, test your generic method with a struct or change the constraint to require that the generic type be a class using where T : class
Try to test it also with struct or add class constraint to the generic method - http://www.codeproject.com/Tips/175592/Code-Coverage-And-Generics
I am trying to build a dynamic Property Accessor. Want something which is like really fast as close to calling the actually Property. Dont want to go the Reflection route as its very slow. So i opted to using DynamicAssembly and inject IL using ILGenerator. Below is the ILGenerator related code which seems to work
Label nulllabel = getIL.DefineLabel();
Label returnlabel = getIL.DefineLabel();
//_type = targetGetMethod.ReturnType;
if (methods.Count > 0)
{
getIL.DeclareLocal(typeof(object));
getIL.DeclareLocal(typeof(bool));
getIL.Emit(OpCodes.Ldarg_1); //Load the first argument
//(target object)
//Cast to the source type
getIL.Emit(OpCodes.Castclass, this.mTargetType);
//Get the property value
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
getIL.Emit(OpCodes.Stloc_0); //Store it
getIL.Emit(OpCodes.Br_S,returnlabel);
getIL.MarkLabel(nulllabel);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Stloc_0);
getIL.MarkLabel(returnlabel);
getIL.Emit(OpCodes.Ldloc_0);
}
else
{
getIL.ThrowException(typeof(MissingMethodException));
}
getIL.Emit(OpCodes.Ret);
So above get the first argument which is the object that contains the property. the methods collection contains the nested property if any. for each property i use EmitCall which puts the the value on the stack and then i try to box it. This works like a charm.
The only issue is if you have a property like Order.Instrument.Symbol.Name and assume that Instrument object is null. Then the code will throw an null object exception.
So this what i did, i introduced a null check
foreach (var methodInfo in methods)
{
getIL.EmitCall(OpCodes.Call, methodInfo, null);
getIL.Emit(OpCodes.Stloc_0);
getIL.Emit(OpCodes.Ldloc_0);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Ceq);
getIL.Emit(OpCodes.Stloc_1);
getIL.Emit(OpCodes.Ldloc_1);
getIL.Emit(OpCodes.Brtrue_S, nulllabel);
getIL.Emit(OpCodes.Ldloc_0);
if (methodInfo.ReturnType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
}
Now this code breaks saying That the object/memory is corrupted etc. So what exactly is wrong with this code. Am i missing something here.
Thanks in Advance.
Previously, if you had consecutive properties P returning string and then Q returning int, you would get something like this:
...
call P // returns string
call Q // requires a string on the stack, returns an int
box
...
Now you have something like this:
...
call P // returns string
store // stores to object
... // load, compare to null, etc.
load // loads an *object*
call Q // requires a *string* on the stack
store // stores to object *without boxing*
...
So I see two clear problems:
You are calling methods in such a way that the target is only known to be an object, not a specific type which has that method.
You are not boxing value types before storing them to a local of type object.
These can be solved by reworking your logic slightly. There are also a few other minor details you could clean up:
Rather than ceq followed by brtrue, just use beq.
There's no point in doing Stloc_1 followed by Ldloc_1 rather than just using the value on the stack since that local isn't used anywhere else.
Incorporating these changes, here's what I'd do:
Type finalType = null;
foreach (var methodInfo in methods)
{
finalType = methodInfo.ReturnType;
getIL.EmitCall(OpCodes.Call, methodInfo, null);
if (!finalType.IsValueType)
{
getIL.Emit(OpCodes.Dup);
getIL.Emit(OpCodes.Ldnull);
getIL.Emit(OpCodes.Beq_S, nulllabel);
}
}
if (finalType.IsValueType)
{
getIL.Emit(OpCodes.Box, methodInfo.ReturnType);
//Box if necessary
}
getIL.Emit(OpCodes.Br_S, returnLabel);
getIL.MarkLabel(nulllabel);
getIL.Emit(OpCodes.Pop);
getIL.Emit(OpCodes.Ldnull);
getIL.MarkLabel(returnlabel);
Note that we can get rid of both locals since we now just duplicate the top value on the stack before comparing against null.
Hey folks, i ve got this issue implementing the Factory method.
Following is the snippet of the the main chart class which calls ChartFactory's method to attain the proper object. I Type Cast chartobject so as to be able to call the Show method;i m apprehensive about that as well.
container = new VBox();
container.percentWidth = 100;
container.percentHeight = 100;
super.media.addChild(container);
chartObject = new ChartBase();
chartObject = ChartFactory.CreateChartObject(chartType);
IChart(chartObject).Show(o);
container.addChild(chartObject);
legend = new Legend();
legend.dataProvider = IChart(chartObject);
container.addChild(legend);
Following is the snippet of ChartFactory's method:
public static function CreateChartObject(subType:String):ChartBase
{
switch(subType)
{
case ChartFactory.AREA_CHART:
return new AreaCharts();
break;
case ChartFactory.COLUMN_CHART:
return new ColumnCharts();
break;
case ChartFactory.PIE_CHART:
return new PieCharts();
break;
default:
throw new ArgumentError(subType + ": Chart type is not recognized.");
}
}
And following is Show method of one of the several Charts type classes: AreaCharts, PieCharts etc. All of which implements IChart Interface.
public function Show(o:ObjectProxy):void
{
var grids:GridLines;
var stroke:SolidColorStroke;
var horizontalAxis:CategoryAxis;
var verticalAxis:LinearAxis;
var horizontalAxisRenderer:AxisRenderer;
var verticalAxisRenderer:AxisRenderer;
grids = new GridLines();
if(WidgetStylesheet.instance.LineChart_ShowGrid)
grids.setStyle("gridDirection", "both");
else
grids.setStyle("gridDirection", "");
stroke = new SolidColorStroke(WidgetStylesheet.instance.LineChart_GridLineColor, WidgetStylesheet.instance.LineChart_GridLineThickness);
grids.setStyle("horizontalStroke", stroke);
grids.setStyle("verticalStroke", stroke);
horizontalAxis = new CategoryAxis();
horizontalAxis.categoryField = o.LargeUrl.Chart.xField;
horizontalAxis.title = o.LargeUrl.Chart.xAxisTitle.toString();
verticalAxis = new LinearAxis();
verticalAxis.title = o.LargeUrl.Chart.yAxisTitle.toString();
horizontalAxisRenderer = new AxisRenderer();
horizontalAxisRenderer.axis = horizontalAxis;
horizontalAxisRenderer.setStyle("tickLength", 0);
horizontalAxisRenderer.setStyle("showLine", false);
horizontalAxisRenderer.setStyle("showLabels", true);
horizontalAxisRenderer.setStyle("fontSize", WidgetStylesheet.instance.ComputeChartAxisFontSize(o.HeadlineFontSize));
verticalAxisRenderer = new AxisRenderer();
verticalAxisRenderer.axis = verticalAxis;
verticalAxisRenderer.setStyle("tickLength", 0);
verticalAxisRenderer.setStyle("showLine", false);
verticalAxisRenderer.setStyle("fontSize", WidgetStylesheet.instance.ComputeChartAxisFontSize(o.HeadlineFontSize));
this.series = this.m_createSeries(o);
this.horizontalAxis = horizontalAxis;
this.horizontalAxisRenderers = [horizontalAxisRenderer];
this.verticalAxis = verticalAxis;
this.verticalAxisRenderers = [verticalAxisRenderer];
this.backgroundElements = [grids];
}
I'm afraid that there is more than one issue with this code. Unfortunately it is not obvious why your chart doesn't show up so you may apply some of advices below and use debugger to analyse the issue.
There is no point in creating ChartBase instance if you are going to change value of chartObject reference in the next line
chartObject = new ChartBase();
chartObject = ChartFactory.CreateChartObject(chartType);
If the API of your charts is IChart your factory should return IChart instead of casting.
public static function CreateChartObject(subType:String):IChart
Make sure that you are returning instances of the correct class from the factory. i.e. that you are returning your subclass of standard PieChart. Generally it's not the best idea to extend the class keeping the same name and just changing the package.
Once again, if you are not sure if the program enters some function use the Flash Builder debugger to check this. I can't imagine development without debugger.
Some thoughts:
you call the Show method, pass it some object but nowhere in that method is any child added to a displayObject. What exactly is Show supposed to do?
a lot of member variables in your classes start with UpperCase. The compiler can easily confuse those with class names, in case your classes are named the same. Bad practice to start variable and function names with capitals.
If your casting an instance to another class or interface fails, you will get a runtime error. Those are easy to debug using the Flash Builder debugger.
Hey ppl..
i found out wat wnt wrng..as olwys it wa "I".
I ve a habit of mkin mock ups secluded from the main project n dn integrate it. So in mock up i hd used an xml whch hd a format slightly diff dn d one being used in the main project.
N i hd a conditional chk to return from the prog if certain value doesnt match, n due to faulty xml i did'nt.
So this more a lexical error than a logical one.
Sorry n Thanx evryone for responding.
My asp.net(c#) method looks as follows:
static public bool GetVideoLength(string fileName, out double length)
{
DirectShowLib.FilterGraph graphFilter = new DirectShowLib.FilterGraph();
DirectShowLib.IGraphBuilder graphBuilder;
DirectShowLib.IMediaPosition mediaPos;
length = 0.0;
try
{
graphBuilder = (DirectShowLib.IGraphBuilder)graphFilter;
graphBuilder.RenderFile(fileName, null);
mediaPos = (DirectShowLib.IMediaPosition)graphBuilder;
mediaPos.get_Duration(out length);
return true;
}
catch
{
return false;
}
finally
{
mediaPos = null;
graphBuilder = null;
graphFilter = null;
}
}
I got the duration with the above method. But my problem is i can't delete the physical file
after my operation. I used
File.Delete(FilePath);
While performing this action i got an exception as follows:
"The process cannot access the file because it is being used by another process."
My Os is windows 7(IIS 7)
Any one please help me to sort this out?
I've got no experience in coding directshow apps in C#, but plenty of experience in C++.
DirectShow is based on a technology called COM - which uses reference counting to tell it when an object is in use.
It would use a COM object to represent the IGraphBuilder for example.
In C++, we would have to deconstruct the graph, by removing all its filters, then release the graph.
I understand that C# has its own garbage collection etc., but unless you explicitly release the objects you use, they'll remain in memory.
It seems from the code you've quoted, that the graph is still opened, even though playback may have finished. In that case, it'll hold a reference to the file which you've played back, which would explain why you can't delete it - e.g. there's a read lock on the file.
Hope this points you in the right direction!