MFC: How do you print contents of a CRichEditView? - printing

I have a simple task where I need to print the contents of a CRichEditView. No scaling needed, No print range, just print contents. Keeping it simple, I tried adding this to the message map:
ON_COMMAND(ID_FILE_PRINT, &CRichEditView::OnFilePrint)
And implementing the virtual function:
BOOL CMyRichView::OnPreparePrinting(CPrintInfo* pInfo)
{
return DoPreparePrinting(pInfo);
}
But when it printed (this is what was actually to be printed):
BOOL CMyRichView::OnPreparePrinting(CPrintInfo* pInfo)
{
return DoPreparePrinting(pInfo);
}
I only got half of the 'r' on return "eturn DoPreparePrinting(pInfo);". So it seems it must have to do with margins or something that the CRichEditView doesn't handle itself?
What am I missing?
TIA!!
EDIT:
I tried changing it to
BOOL CMyRichView::OnPreparePrinting(CPrintInfo* pInfo)
{
// note a MM_TWIPS is 1/1440 of an inch.
// create 1/2" margin which most printers support
CSize sizepaper = GetPaperSize();
CRect rectmargins(720, 720, sizepaper.cx - 720, sizepaper.cy - 720);
// Need to set the margins when printing from CRichEditView
SetMargins(rectmargins);
// per SetMargins API reference, call wrapchanged
if (m_nWordWrap==WrapToTargetDevice) {
WrapChanged();
}
return DoPreparePrinting(pInfo);
}
But now it just spits out tons of blank pieces of paper. I also tried it within the virtual function OnPrint(CDC* pDC, CPrintInfo* pInfo) prior to calling the base class. Same result, so deleted OnPrint() (not using it).
EDIT:
So I took that sample above from the GetPaperSize() documentation. But it was wrong. It works using this (which the documentation for SetPaperSize() uses).
BOOL CMyRichView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
// note a MM_TWIPS is 1/1440 of an inch.
// Need to set the margins when printing from CRichEditView
SetMargins(CRect(720, 720, 720, 720));
// per SetMargins API reference, call wrapchanged
if (m_nWordWrap==WrapToTargetDevice) {
WrapChanged();
}
return __super::OnPrint(pDC, pInfo);
}

The answer is:
ON_COMMAND(ID_FILE_PRINT, &CRichEditView::OnFilePrint)
BOOL CMyRichView::OnPreparePrinting(CPrintInfo* pInfo)
{
return DoPreparePrinting(pInfo);
}
BOOL CMyRichView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
// note a MM_TWIPS is 1/1440 of an inch.
// Need to set the margins when printing from CRichEditView
SetMargins(CRect(720, 720, 720, 720));
// per SetMargins API reference, call wrapchanged
if (m_nWordWrap==WrapToTargetDevice) {
WrapChanged();
}
return __super::OnPrint(pDC, pInfo);
}

Related

How to correctly grab matrix from Queue (opencv)

I try to make frame grabber class from IP Camera using std::queue and opencv
In this class, It takes and store maximum 10 frame,
and Other class, get frame from buffer.
/* Camera.cpp */
struct FRAME
{
cv::Mat Img;
uint64_t Time;
bool ReadError;
};
class Camera
{
std::queue<FRAME> m_buffer;
std::mutex m_buffer_mutex;
...
};
void Camera::threadFunc_get_stream_from_camera()
{
while (true)
{
FRAME frame;
... // read sequence (if cv::read is fail, store frame routine is skipping)
m_buffer_mutex.lock();
while (m_buffer.size() >= 10)
m_buffer.pop();
m_buffer.push(frame);
m_buffer_mutex.unlock();
}
}
FRAME Camera::grab()
{
std::unique_lock ulock(m_buffer_mutex);
FRAME frame;
if (m_buffer.empty() == false)
{
frame = m_buffer.front();
m_buffer.pop();
return frame;
}
}
/***************/
/* Testing.cpp */
int main()
{
// Camera* cam ..
...
while (true)
{
auto frame = cam->grab();
if (frame.Img.data == nullptr || frame.Time == 0)
continue;
... // frame image processing
}
}
I kept the program this way for about 3 days, and no special bugs or memory sticks were found.
But the reason I'm asking this question is,
whether it's right to use non-pointer(FRAME) in grab() function.
I'm using C++17, and I think there is no problem because the uint64_t or bool values in the structure are copied in this version.
but, How about cv::Mat ?
I don't want to using Producer-Consumer pattern, because not want to contain testing class side's code in Camera class.

how to progressively add drawable to a canvas?

I have points generated one by one, and when a new point is generated, I want to draw a line segment connecting with the previous point. Like this:
var x by remember { mutableStateOf( 0.0f)}
var y by remember { mutableStateOf( 0.5f)}
var pStart by remember { mutableStateOf(Offset(0f, 0.5f))}
Canvas(modifier = Modifier.fillMaxSize()) {
canvasWidth = size.width
canvasHeight = size.height
val pEnd = Offset(x * canvasWidth, (1-y) * canvasHeight)
val col = if (pEnd.y < pStart.y) Color.Green else Color.Red
drawLine(
start = pStart,
end = pEnd,
strokeWidth = 4f,
color = col
)
pStart = pEnd
}
But this only draws the segment in a flash and no segments stay on the screen.
I know I can save the points to a list and redraw all the segments whenever a new point is added. But I just hope to economize. Is it possible?
There's no practical other way. You COULD in fact, keep track of just two points, adding a whole new Canvas (all Transparent and Filling the maximum Size, stacked on top of one another), for each extra point that is added. This does seem a bit impractical, but maybe try it out and do some benchmarking to see which one checks out. This is the only OTHER way I could think of, where you do not have to store all the points and recompose every time a point is added, since all the other lines would technically be frozen in space.
In response to the somewhat (unreasonably) aggressive comment below, here's some sample code. I assume you have a stream of new points coming in so a LiveData object is assumed to be the source of that, which I shall be converting to a MutableState<T> for my use-case.
var latestPoint by liveData.collectAsState()
var recordedPoint by remember { mutableStateOf(latestPoint) }
var triggerDraw by remember { mutableStateOf(false) }
var canvasList = mutableStateListOf<#Composable () -> Unit>Canvas>() // Canvas is the Composable
if(triggerDraw){
canvasList.add(
Canvas(){
/* you have the recordedPoint, and latestPoint, simply draw a line here */
}
)
triggerDraw = false
}
LaunchedEffect(latestPoint){
triggerDraw = true
}
canvasList.forEach {
it() // Invoke the Composable here
}
Thanks Dad!

How do I only respond to touches within a UI Image?

I have been wracking my brain and using every Google search phrase I can think of and have yet to find a solution.
I have a Unity app with a 3D scene and UI elements that float over it. There is one UI element that is an image of a protractor. That image needs to be drug around the scene, rotated, and scaled. All of that works, the only catch is that is doesn't matter if the user touches the protractor or somewhere else, the protractor always reacts.
I started by looking for something along the lines of Swift's someCGRect.contains(someCGPoint) so that I could ignore anything that isn't in the bounds of the protractor. Image doesn't seem to have such a property so I did lots of other searching.
I finally found this video; https://www.youtube.com/watch?v=sXc8baUK3iY that has basically what I'm looking for… Except is doesn't work.
The video uses a collider and rigid body and then in code checks to see if the collider overlaps the touch point. Looks like exactly what I need. Unfortunately, no touches ever overlap with the collider no matter where they are. After some Debug.Log I found that the extents of the collider are reported as (0, 0, 0). This is clearly why none of the touches overlap with it, but I can't figure out how to make the extents be anything other than 0.
Here is the info from the colliders and rigid body attached to the image:
Box Collider 2D:
Used by Composite: true
Auto Tiling: false
Offset: (0,0)
Size: (1,1)
Rigidbody 2D:
Body Type: Kinematic
Material: None (Physics Material 2D)
Simulated: true
Use Full Kinematic Contact: false
Collision Detection: Discrete
Sleeping Mode: Start Awake
Interpolate: None
Constraints: None
Composite Collider 2D:
Material: None (Physics Material 2D)
is Trigger: false
Used By Effector: false
Offset: (0,0)
Geometry Type: Polygons
Generation Type: Synchronous
Vertex Distance: 0.0005
There is a button that turns the protractor on and off by use of the following code:
public void toggle() {
this.enabled = !this.enabled;
this.gameObject.SetActive(this.enabled);
}
The protractor starts life visible but Start() calls toggle() straight away so the user sees it as starting out off.
This is the code that performs the test to see if the touches should be responded to:
void checkTouches() {
if (Input.touchCount <= 0) {
return;
}
bool oneTouchIn = false;
Collider2D collider = GetComponent<Collider2D>();
Debug.Log("🔵 The bounds of the collider are: " + collider.bounds);
// The above always logs the extents as (0,0,0).
foreach (Touch touch in Input.touches) {
Vector2 touchPos = Camera.main.ScreenToWorldPoint(touch.position);
if(collider.OverlapPoint(touchPos)) {
// Since the extents are all 0 we never find any overlaps
oneTouchIn = true;
break;
}
}
if (!oneTouchIn) {
return; // Always ends up here
}
// We must have at least one touch that is in our bounds.
// Do stuff with the touch(es) here…
}
I've been doing iOS development with Objective-C since the SDK was released and with Swift since it come out but I'm very new to Unity. I'm sure the issue is me missing something silly, but I can't find it.
Does anyone know what I'm missing to make the current version work or an alternate way of only responding to touches that are in bounds?
Image doesn't seem to have such a property
No the Image componemt itself doesn't have that ...
But the rect property of the RectTransform component each UI GameObject has.
It is called Contains. So you could do e.g.
RectTransform imgRectTransform = imageObject.GetComponent<RectTransform>();
Vector2 localTouchPosition = imgRectTransform.InverseTransformPoint(Touch.position);
if (imgRectTransform.rect.Contains(localToichPosition)) { ... }
Alternatively you could use the IPointerEnterHandler and IPointerExitHandler Interfaces in a component on the target Image like e.g.
public class DragableHandler : MonkBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public bool IsHover {get; private set; }
//Detect if the Cursor starts to pass over the GameObject
public void OnPointerEnter(PointerEventData pointerEventData)
{
//Output to console the GameObject's name and the following message
Debug.Log("Cursor Entering " + name + " GameObject");
IsHover = true;
}
//Detect when Cursor leaves the GameObject
public void OnPointerExit(PointerEventData pointerEventData)
{
//Output the following message with the GameObject's name
Debug.Log("Cursor Exiting " + name + " GameObject");
IsHover = false;
}
}
and than in your script check it using
if(imageObject.GetComponent<DragableHandler>().IsHover) { ... }
just also make sure that we the EventSystem you also add Touch Input Module and check the flag Force Module Active.

Strange File Save Behavior with ImageJ

I wrote an imageJ script to color and merge a series of black and white images. The script saves both the unmerged colored images and merged colored images. Everything works beautifully when I'm running in debug mode and step through the script. When I run it for real, however, it occasionally saves a couple of the original black and whites instead of the resulting colored image. All the merged images appear to be fine.
Why would everything work fine in debug mode but fail during regular usage?
Below is my code :
// Choose the directory with the images
dir = getDirectory("Choose a Directory ");
// Get a list of everything in the directory
list = getFileList(dir);
// Determine if a composite directory exists. If not create one.
if (File.exists(dir+"/composite") == 0) {
File.makeDirectory(dir+"/composite")
}
// Determine if a colored directory exists. If not create one.
if (File.exists(dir+"/colored") == 0) {
File.makeDirectory(dir+"/colored")
}
// Close all files currently open to be safe
run("Close All");
// Setup options
setOption("display labels", true);
setBatchMode(false);
// Counter 1 keeps track of if you're on the first or second image of the tumor/vessel pair
count = 1;
// Counter 2 keeps track of the number of pairs in the folder
count2 = 1;
// Default Radio Button State
RadioButtonDefault = "Vessel";
// Set Default SatLevel for Contrast Adjustment
// The contrast adjustment does a histogram equalization. The Sat Level is a percentage of pixels that are allowed to saturate. A larger number means more pixels can saturate making the image appear brighter.
satLevelDefault = 2.0;
// For each image in the list
for (i=0; i<list.length; i++) {
// As long as the name doesn't end with / or .jpg
if (endsWith(list[i], ".tif")) {
// Define the full path to the filename
fn = list[i];
path = dir+list[i];
// Open the file
open(path);
// Create a dialog box but don't show it yet
Dialog.create("Image Type");
Dialog.addRadioButtonGroup("Type:", newArray("Vessel", "Tumor"), 1, 2, RadioButtonDefault)
Dialog.addNumber("Image Brightness Adjustment", satLevelDefault, 2, 4, "(applied only to vessel images)")
// If it's the first image of the pair ...
if (count == 1) {
// Show the dialog box
Dialog.show();
// Get the result and put it into a new variable and change the Default Radio Button State for the next time through
if (Dialog.getRadioButton=="Vessel") {
imgType = "Vessel";
RadioButtonDefault = "Tumor";
} else {
imgType = "Tumor";
RadioButtonDefault = "Vessel";
}
// If it's the second image of the pair
} else {
// And the first image was a vessel assume the next image is a tumor
if (imgType=="Vessel") {
imgType="Tumor";
// otherwise assume the next image is a vessel
} else {
imgType="Vessel";
}
}
// Check to see the result of the dialog box input
// If vessel do this
if (imgType=="Vessel") {
// Make image Red
run("Red");
// Adjust Brightness
run("Enhance Contrast...", "saturated="+Dialog.getNumber+" normalize");
// Strip the .tif off the existing filename to use for the new filename
fnNewVessel = replace(fn,"\\.tif","");
// Save as jpg
saveAs("Jpeg", dir+"/colored/"+ fnNewVessel+"_colored");
// Get the title of the image for the merge
vesselTitle = getTitle();
// Othersie do this ...
} else {
// Make green
run("Green");
// Strip the .tif off the existing filename to use for the new filename
fnNewTumor = replace(fn,"\\.tif","");
// Save as jpg
saveAs("Jpeg", dir+"/colored/"+ fnNewTumor+"_colored");
// Get the title of the image for the merge
tumorTitle = getTitle();
}
// If it's the second in the pair ...
if (count == 2) {
// Merge the two images
run("Merge Channels...", "c1="+vesselTitle+" c2="+tumorTitle+" create");
// Save as Jpg
saveAs("Jpeg", dir+"/composite/composite_"+count2);
// Reset the number within the pair counter
count = count-1;
// Increment the number of pairs counter
count2 = count2+1;
// Otherwise
} else {
// Increment the number within the pair counter
count += 1;
}
}
}
Not sure why I'd need to do this but adding wait(100) immediately before saveAs() seems to do the trick
The best practice in this scenario would be to poll IJ.macroRunning(). This method will return true if a macro is running. I would suggest using helper methods that can eventually time out, like:
/** Run with default timeout of 30 seconds */
public boolean waitForMacro() {
return waitForMacro(30000);
}
/**
* #return True if no macro was running. False if a macro runs for longer than
* the specified timeOut value.
*/
public boolean waitForMacro(final long timeOut) {
final long time = System.currentTimeMillis();
while (IJ.macroRunning()) {
// Time out after 30 seconds.
if (System.currentTimeMillis() - time > timeOut) return false;
}
return true;
}
Then call one of these helper methods whenever you use run(), open(), or newImage().
Another direction that may require more work, but provide a more robust solution, is using ImageJ2. Then you can run things with a ThreadService, which gives you back a Java Future which can then guarantee execution completion.

Android MediaCodec: how to request a key frame when encoding

In Android4.1, a key frame is often requested in a real-time encoding application. But how to do it using MediaCodec object? The current Android4.2 SDK seems not support it.
You can produce random keyframe by specifying MediaCodec.BUFFER_FLAG_SYNC_FRAME when queuing input buffers:
MediaCodec codec = MediaCodec.createDecoderByType(type);
codec.configure(format, ...);
codec.start();
ByteBuffer[] inputBuffers = codec.getInputBuffers();
for (;;) {
int inputBufferIndex = codec.dequeueInputBuffer(timeoutUs);
if (inputBufferIndex >= 0) {
// fill inputBuffers[inputBufferIndex] with valid data
...
codec.queueInputBuffer(inputBufferIndex, 0, inputBuffers[inputBufferIndex].limit(), presentationTime,
isKeyFrame ? MediaCodec.BUFFER_FLAG_SYNC_FRAME : 0);
}
}
Stumbled upon the need to insert random keyframe when encoding video on Galaxy Nexus.
On it, MediaCodec didn't automatically produce keyframe at the start of the video.
MediaCodec has a method called setParameters which comes to the rescue.
In Kotlin you can do it like:
fun yieldKeyFrame(): Boolean {
val param = Bundle()
param.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0)
try {
videoEncoder.setParameters(param)
return true
} catch (e: IllegalStateException) {
return false
}
}
in above snippet, the videoEncoder is an instance of MediaCodec configured to encode.
You can request a periodic key frame by setting the KEY_I_FRAME_INTERVAL key when configuring the encoder. In the example below I am requesting one every two seconds. I've omitted the other keys like frame rate or color format for the sake of clarity, but you will still want to include them.
encoder = MediaCodec.createByCodecName(codecInfo.getName());
MediaFormat inputFormat = MediaFormat.createVideoFormat(mimeType, width, height);
/* ..... set various format options here ..... */
inputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);
encoder.configure(inputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
I suspect, however, that what you are really asking is how to request a random key frame while encoding, like at the start of a cut scene. Unfortunately I haven't seen an interface for that. It is possible that stopping and restarting the encoder would have the effect of creating a new key frame at the restart. When I have the opportunity to try that, I'll post the result here.
I hope this was helpful.
Thad Phetteplace - GLACI, Inc.

Resources